Я хочу получить родительский каталог файла из файла .bat
. Поэтому, если переменная установлена в "C:\MyDir\MyFile.txt"
, я бы хотел получить "C:\MyDir"
. Другими словами, эквивалент функциональности dirname()
в типичной среде UNIX. Возможно ли это?
Как получить эквивалент dirname() в пакетном файле?
Ответ 1
for %%F in (%filename%) do set dirname=%%~dpF
Это установит %dirname%
в дисковод и каталог имени файла, хранящегося в %filename%
.
Осторожно с именами файлов, содержащих пробелы. Либо они должны быть установлены с окружающими кавычками:
set filename="C:\MyDir\MyFile with space.txt"
или вам нужно поставить кавычки вокруг аргумента в цикле for
:
for %%F in ("%filename%") do set dirname=%%~dpF
Любой из этих методов будет работать, и в то же время не будет: -)
Ответ 2
Если по какой-либо причине вы не можете использовать FOR (без командных расширений и т.д.), вы можете уйти с помощью.. \hack:
set file=c:\dir\file.txt
set dir=%file%\..\
Ответ 3
Проблема с циклом for заключается в том, что она оставляет конечный символ\в конце строки. Это вызывает проблемы, если вы хотите получить имя dirname несколько раз. Возможно, вам нужно получить имя каталога, являющегося прародителем каталога, содержащего этот файл, а не только родительский каталог. Просто используя технику for loop второй раз удалит\и не получит каталог grandparent.
То есть вы не можете просто сделать следующее.
set filename=c:\1\2\3\t.txt
for %%F in ("%filename%") do set dirname=%%~dpF
for %%F in ("%dirname%") do set dirname=%%~dpF
Это установит dirname в "c:\1\2\3", а не "c:\1\2".
Следующая функция решает эту проблему, также удаляя конечную \.
:dirname file varName
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET _dir=%~dp1
SET _dir=%_dir:~0,-1%
endlocal & set %2=%_dir%
GOTO :EOF
Он вызывается следующим образом.
set filename=c:\1\2\3\t.txt
call :dirname "%filename%" _dirname
call :dirname "%_dirname%" _dirname