Как получить эквивалент dirname () в командном файле? - PullRequest
21 голосов
/ 22 апреля 2009

Я бы хотел получить родительский каталог файла из файла .bat. Итак, учитывая переменную, установленную на "C:\MyDir\MyFile.txt", я бы хотел получить "C:\MyDir". Другими словами, эквивалент dirname() функциональности в типичной среде UNIX. Возможно ли это?

Ответы [ 3 ]

24 голосов
/ 22 апреля 2009
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

Любой метод будет работать, оба одновременно не будут: -)

6 голосов
/ 12 мая 2009

Если по какой-либо причине вы не можете использовать FOR (без расширений команд и т. Д.), Вам, возможно, удастся избежать неприятностей с .. \ hack:

set file=c:\dir\file.txt
set dir=%file%\..\
3 голосов
/ 17 июня 2014

Проблема с циклом for состоит в том, что он оставляет завершающий символ \ в конце строки. Это вызывает проблемы, если вы хотите получить dirname несколько раз. Возможно, вам нужно получить имя каталога, который является прародителем каталога, содержащего файл, а не просто родительский каталог. Простое использование метода for во второй раз приведет к удалению \ и не приведет к каталогу дедушки.

То есть вы не можете просто сделать следующее.

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
...