Windows CMD CD в новейший каталог - PullRequest
0 голосов
/ 21 июня 2019

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

Я знаю, как это сделать в bash (уже было задано здесь ), но я не знаю, как сделать то же самое в Windows cmd. Кто-нибудь может мне помочь?

1 Ответ

2 голосов
/ 25 июня 2019

В пакетном файле следующие строки могут использоваться для перехода в подкаталог с самой новой датой изменения:

@echo off
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do cd "%%I" & goto DoneCD
echo No subdirectory found in: "%CD%"
:DoneCD

Команда FOR с параметром /F запускает новый процесс командыс %ComSpec% /c и командной строкой, указанной между ' в качестве дополнительных аргументов в фоновом режиме.Таким образом, выполнение FOR осуществляется с использованием обычного пути установки Windows:

C:\Windows\System32\cmd.exe /c dir * /AD /B /O-D 2>nul

DIR , выполняемого в фоновом режиме при поиске команды с указанными аргументами

  • в текущем каталоге
  • для каталогов из-за опции /AD (каталог атрибутов)
  • , совпадающей с шаблоном подстановки * (все)

и выходных данных

  • в голом формате из-за опции /B только имена каталогов без пути никогда не заключаются в "
  • в обратном порядке по дате последнего изменения из-за опции /O-D и неиспользуя опцию /TC (дата создания) или /TA (дата последнего доступа), что означает сначала самый новый измененный каталог и последний самый старый измененный каталог.

Вывод DIR записывается для обработки STDOUT запущенного фонового командного процесса.

2>nul перенаправляет вывод сообщения об ошибке с помощью DIR при не обнаружении какого-либо каталога в текущем директореy от дескриптора STDERR до устройства NUL для подавления этого сообщения об ошибке.

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

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

FOR игнорирует пустые строки, которые здесь не появляются из-за DIR выходовсписок имен каталогов без пустых строк из-за использования /B.

FOR по умолчанию разделил бы строку на подстроки (токены) с использованием обычного пробела и символа горизонтальной табуляции в качестве разделителей.После этого разбиения подстроки FOR по умолчанию проверит, начинается ли первая подстрока с символом конца строки по умолчанию ;, и в этом случае строка будет игнорироваться как пустая строка.В противном случае FOR назначит строку с пробелом / символом табуляции для указанной переменной цикла I и выполнит командную строку с CD и GOTO .

Имя каталога может быть, например, ;Test Folder, то есть имя каталога, начинающееся с пробела и точки с запятой и содержащее еще один пробел.Такое имя каталога будет разделено на ;Test (без пробела в начале) и Folder, а затем игнорируется FOR , поскольку ;Test начинается с точки с запятой.

ForПо этой причине символ конца строки переопределяется с точки с запятой по умолчанию на вертикальную черту с eol=|, то есть символом, который не может содержать имя файла или папки в соответствии с документацией Microsoft о Именование файлов, путей и пространств имен .И поведение разделения строки отключено с delims= в конце строки аргумента параметров после for /F, которая определяет пустой список разделителей.Таким образом, имя каталога, выводимое DIR , присваивается переменной цикла I без каких-либо изменений, даже если это очень необычное имя для каталога.

FOR выполняет команду CD , которая изменяет текущий каталог на последний измененный подкаталог текущего каталога, и следующая команда GOTO выполняется для продолжения обработки командный файл в строке ниже строки метки :DoneCD. Таким образом, выполнение цикла FOR прерывается уже после обработки первого имени каталога командой GOTO .

Разумеется, можно использовать другие команды после командной строки FOR и строки метки :DoneCD, кроме строки ECHO , сообщающей, что в текущем каталоге не найдено подкаталога как показано путем ссылки на динамическую переменную среды CD, например, на командную строку для выхода из пакетной обработки в этом необычном случае использования или в случае ошибки.

Эта FOR командная строка с командой GOTO для выхода из цикла FOR после CD не может использоваться в окне командной строки Windows , Решение для окна командной строки Windows будет:

set "DoneCD=" & (@for /F "eol=| delims=" %I in ('dir * /AD /B /O-D 2^>nul') do @if not defined DoneCD cd "%I" & set "DoneCD=1") & set "DoneCD="

В пакетном файле эта одна строка с несколькими командами будет записана как

@set "DoneCD=" & (@for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do @if not defined DoneCD cd "%%I" & set "DoneCD=1") & set "DoneCD="

или лучше читаемый в своей многострочной версии с дополнительным echo как

@echo off
set "DoneCD="
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do (
    if not defined DoneCD (
        cd "%%I"
        set "DoneCD=1"
    )
)
if not defined DoneCD echo No subdirectory found in: "%CD%"
set "DoneCD="

Сначала переменная окружения DoneCD удаляется, если она определена случайно.

Далее FOR выполняет cmd.exe с DIR , как описано выше, и обрабатывает первый выходной каталог с самой новой датой изменения. Условие IF верно для новейшего каталога, поскольку переменная среды была определенно неопределена до выполнения FOR . Таким образом, команда CD выполняется для изменения текущего каталога на новейший подкаталог. Тогда переменная окружения DoneCD определяется со значением 1. Любое другое значение также возможно, как при использовании set "DoneCD=%%I". Здесь важно то, что для других подкаталогов, выводимых DIR , переменная окружения DoneCD теперь определена, поэтому условие IF всегда ложно. Таким образом, в текущем подкаталоге исходного текущего каталога не делается никаких попыток изменить его на подкаталог, не существующий здесь или случайно существующий также в подкаталоге.

Наконец, переменная окружения DoneCD снова удаляется, если вообще определяется во время выполнения FOR .

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

  • cd /?
  • dir /?
  • echo /?
  • for /?
  • goto /?
  • if /?
  • set /? ... объяснение на последней странице справки динамическая переменная среды CD.
...