Почему% CD% не работает в цикле for с PushD - PullRequest
0 голосов
/ 05 декабря 2018

Я хочу запустить скрипт .bat, который создает файл и сохранить его с тем же именем, что и папка, в которой он находится. Я хочу, чтобы он запускался на карте и проходил по подкартам.Я начал с этого кода ниже и запустил его в одном из вложенных карт.Это работает, я получаю файл с именем подкарты.

FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
ECHO Last segment = "%_LAST_SEGMENT_%"
echo.>%_LAST_SEGMENT_%.mp4
pause

Так что теперь мне нужно только поместить его в цикл for.Поэтому я сделал код ниже, который не работает.Похоже, что %CD% относится к моей родительской карте (подпапки), в которой находится файл .bat вместо моих подкарт (видео1, видео2 и т. Д.).

Set Base=C:\Video\subfolders
FOR /R "%Base%" %%F IN (.) DO (
    PushD "%%F"
        FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
        echo %CD%
        ECHO Last segment = "%_LAST_SEGMENT_%"
        echo.>%_LAST_SEGMENT_%.mp4
    PopD
)
Pause

Вывод:

C:\Video\subfolders>Set Base=C:\Video\subfolders
C:\Video\subfolders>FOR /R "C:\Video\subfolders" %F IN (.) DO (
PushD "%F"
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders>(
PushD "C:\Video\subfolders\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video1\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders\video1>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video2\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders\video2>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video3\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders\video3>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>Pause
Press any key to continue . . .

Я видел ссылку ниже, которая объясняет использование setlocal enabledelayedexpansion, но я не могу заставить это работать.

https://superuser.com/questions/503488/why-doesnt-cd-work-after-using-pushd-to-a-unc-path

Любой совет будетцениться

1 Ответ

0 голосов
/ 05 декабря 2018

Похоже, вы хотите что-то вроде:

@echo off
for /F "delims=" %%I in ('dir "C:\Video\subfolders\*" /AD-H /B /S 2^>nul') do (
    pushd "%%I"
    echo/>"%%~nxI.mp4"
    popd
)

Команды pushd и popd на самом деле не нужны, как показано с помощью кода ниже:

@echo off
for /F "delims=" %%I in ('dir "C:\Video\subfolders\*" /AD-H /B /S 2^>nul') do (
    echo Directory is: %%I
    echo/>"%%I\%%~nxI.mp4"
)

Команда FOR выполняется в отдельном командном процессе, запущенном с cmd.exe /C в фоновом режиме командной строки:

dir "C:\Video\subfolders\*" /AD-H /B /S 2>nul

Команда DIR выводит для обработки STDOUT этого фонового командного процесса

  • в голом формате из-за опции /B только все имена с полным путем из-за опции /S
  • не скрытых каталогов из-заопция /AD-H (каталог атрибутов и не скрытый)
  • в указанном каталоге C:\Video\subfolders и всех его подкаталогах.

Сообщение об ошибке, выводимое DIR toдескриптор STDERR при обнаружении какой-либо записи каталога во всем дереве каталогов C:\Video\subfolders подавляется путем перенаправления его на устройство NUL .

Прочтите статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul.Оператор перенаправления > должен быть экранирован с помощью символа вставки ^ в FOR командной строке, чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , котораявыполняет встроенную командную строку dir в отдельном командном процессе, запущенном в фоновом режиме.

FOR записывает выходные данные в STDOUT запущенного командного процесса и обрабатывает эту выходную строкустрока с игнорированием пустых строк и по умолчанию также строки, начинающиеся с точки с запятой, которые здесь не встречаются.

FOR также разделит каждую строку на подстроки на пробелах / табуляциях и назначиттолько первая строка, разделенная пробелом / табуляцией, для указанной переменной цикла I.Имена каталогов могут содержать пробелы, и по этой причине delims= используется для определения пустого списка разделителей строк, в результате чего присваивается переменная цикла I, всегда полное полное имя каталога, которое в настоящее время обрабатывается из захваченного DIR output.

На имя каталога без пути ссылается %%~nxI, который является строкой после последней обратной косой черты.Имя каталога может также содержать точку, такую ​​как folder.name, или начинаться с точки, такой как .FolderName, хотя в Windows они оба необычны.По этой причине необходимо использовать %%~nxI (имя и расширение), а не просто %%~nI, поскольку FOR не проверяет, является ли строка, на которую указывает %%I, имя файла или каталога.

%%~nI ссылается на строку между last \ (или / для совместимости с путями Linux, все сначала заменены на \), если есть какой-либо обратный слеш (или косая черта) вообще или начало строки, если нет \ (или /) и последняя точка, если вообще есть . после уже определенного начала строки имени или конец строки, если нет точки.%%~xI ссылается на строку, начинающуюся с последней точки, найденной после последнего разделителя каталогов.Таким образом, строка, назначенная переменной цикла I, не должна быть именем файла / папки реально существующего файла / папки, хотя здесь это имеет место.%%~nxI будет пустой строкой, если I содержит строку, заканчивающуюся \ (или /).

Не назначайте строку, на которую можно ссылаться, используя переменную цикла без или смодификатор переменной среды, так как для этого потребуется использовать отложенное расширение , как объяснено с помощью команды SET вывод при запуске в окне командной строки set /?.

Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.

  • dir /?
  • echo /?
  • for /?
  • popd /?
  • pushd /?

См. Также тему форума DosTips ЭХО.НЕ УКАЗАН, чтобы дать текст или пустую строку. Вместо этого используйте ECHO / .

Код второго пакетного файла, о котором идет речь, не работает из-за того, что не используется отложенное расширение или избегается использование переменных среды, определенных / измененных внутрикомандный блок и ссылка на него в том же командном блоке с использованием синтаксиса %variable%.Командный процессор Windows cmd.exe анализирует весь командный блок с ( первого FOR до соответствия ) перед выполнением внешнего FOR в первый раз.См. Как синтаксический анализ сценариев интерпретатора команд Windows (CMD.EXE)? Все ссылки %variable% в этом блоке команд уже заменяются на этом этапе предварительной обработки на текущее значение указанной переменной среды.Таким образом, код, окончательно выполненный при итерации внешнего FOR , больше не содержит никаких ссылок на переменные окружения %variable%, как это можно увидеть в командной строке, выводимой cmd.exe перед выполнением командной строки.

...