Get parent directory name for a particular file using DOS Batch scripting
I need to find the name of the parent directory for a file in DOS
for ex.
Suppose this is the directory
C:\test\pack\a.txt
I have a script which asks me the file name
C:\\>getname.bat
enter file name: c:\test\pack\a.txt
now the script shou开发者_StackOverflow中文版ld return just the parent name of the file.
pack
and NOT the entire parent path to the file.
c:\test\pack
It can be very simple to get the parent folder of the batch file:
@echo off
for %%a in ("%~dp0\.") do set "parent=%%~nxa"
echo %parent%
And for a parent of a file path as per the question:
@echo off
for %%a in ("c:\test\pack\a.txt") do for %%b in ("%%~dpa\.") do set "parent=%%~nxb"
echo %parent%
First answer above does not work if parent directory name contains a space. The following works:
@echo off
setlocal
set ParentDir=%~p1
set ParentDir=%ParentDir: =:%
set ParentDir=%ParentDir:\= %
call :getparentdir %ParentDir%
set ParentDir=%ParentDir::= %
echo ParentDir is %ParentDir%
goto :EOF
:getparentdir
if "%~1" EQU "" goto :EOF
Set ParentDir=%~1
shift
goto :getparentdir
Calling the above with parameter of "C:\Temp\Parent Dir With Space\myfile.txt" gives following:
>GetParentDir "C:\Temp\Parent Dir With Space\myfile.txt"
ParentDir is Parent Dir With Space
The above works by replacing spaces with colons (these should not exist in Windows paths), then replacing directory delimiters with spaces to so individual directories are passed to getparentdir as separate arguments. Function getparentdir loops until it finds its last argument. Finally any colons in result are replaced by spaces.
see this question
@echo OFF set mydir="%~p1" SET mydir=%mydir:\=;% for /F "tokens=* delims=;" %%i IN (%mydir%) DO call :LAST_FOLDER %%i goto :EOF :LAST_FOLDER if "%1"=="" ( @echo %LAST% goto :EOF ) set LAST=%1 SHIFT goto :LAST_FOLDER
you can use a vbscript, eg save the below as getpath.vbs
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
WScript.Echo objFS.GetParentFolderName(strFile)
then on command line or in your batch, do this
C:\test>cscript //nologo getpath.vbs c:\test\pack\a.txt
c:\test\pack
If you want a batch method, you can look at for /?
.
%~fI - expands %I to a fully qualified path name
%~dI - expands %I to a drive letter only
%~pI - expands %I to a path only
Here's a way that does not use CALL
and I believe is faster.Based on jeb's splitting function (might fail if the directory name contains !
) :
@echo off
set "mydir=%~p1"
SET mydir=%mydir:~0,-1%
setlocal EnableDelayedExpansion
set LF=^
rem ** Two empty lines are required
for %%L in ("!LF!") DO (
set "dir_name=!mydir:\=%%L!"
)
for /f "delims=" %%P in (""!dir_name!"") do set "dn=%%~P"
echo %dn%
exit /b 0
I found this combination of approaches from the answers of djangofan and paranoid to be both, simple and perfectly sufficient, when looking up my script's parent directory:
set FULL_PATH=%~dp0
set FULL_PATH=%FULL_PATH:~1,-1%
for %%i in ("%FULL_PATH%") do set "PARENT_FOLDER=%%~ni"
echo %PARENT_FOLDER%
Since you want to work on user input instead, you have to do some minimal additional work, to handle legal variations like C:\foo\bar\a.txt vs. C:\foo\bar\a.txt or c:/foo/bar/a.txt. This might then work for you:
@setlocal
@echo off
call:GET_PARENT_FOLDER C:\foo\bar\a.txt
echo %PARENT_FOLDER%
call:GET_PARENT_FOLDER C:\foo\bar\\a.txt
echo %PARENT_FOLDER%
call:GET_PARENT_FOLDER c:/foo/bar/a.txt
echo %PARENT_FOLDER%
pause
goto:EOF
:GET_PARENT_FOLDER
:: Strip the filename, so we get something like this: 'C:\foor\bar\'
set "_FULL_PATH=%~dp1"
:: Strips all dangling '\' and '/' in a loop, so the last folder name becomes accessible
:_STRIP
if not "%_FULL_PATH:~-1%"=="\" if not "%_FULL_PATH:~-1%"=="/" goto:_STRIP_END
set "_FULL_PATH=%_FULL_PATH:~1,-1%"
goto:_STRIP
:_STRIP_END
:: We need the context of a for-loop for the special path operators to be available
for %%i in ("%_FULL_PATH%") do set "PARENT_FOLDER=%%~ni"
goto:EOF
The idea of DaDummy worked out in more practical reuseable functions. Also the first character of the _full_path is now included.
set map=D:\test1\test2\test3\test4.txt
call:get_parent_path "%map%"
echo full_path is %_full_path%
call:get_parent_path %_full_path%
echo full_path is %_full_path%
call:get_last_path %_full_path%
echo last_path is %_last_path%
goto :eof
:get_parent_path
set "_full_path=%~dp1"
:_strip
if not "%_full_path:~-1%"=="\" if not "%_full_path:~-1%"=="/" goto:_strip_end
set "_full_path=%_full_path:~0,-1%"
goto:_strip
:_strip_end
exit /b
:get_last_path
set "_last_path=%~nx1"
exit /b
::result:
::full_path is D:\test1\test2\test3
::full_path is D:\test1\test2
::last_path is test2
Here is another solution:
SET LAST=%CD%
SET PARENTNAME=NONE
cd /D C:\test\pack
FOR %%I in (%CD%) do SET PARENTNAME=%%~nI
cd /D %LAST%
ECHO %PARENTNAME%
%%~nI: '~n' extracts name from path stored in %%I variable
cd: '/D' parameter added to switch between disks also
call :set_dirname "%cd%"
echo %DIRNAME%
:set_dirname
set DIRNAME=%~n1
goto :eof
精彩评论