Пакетный файл MS Windows: нужно цикл за несколько строк - PullRequest
1 голос
/ 21 июня 2019

Я хочу, чтобы пакетный файл удалял ненужные папки; его команды должны иметь ограниченную ширину.

Вот что у меня работает, но слишком долго:

for /d /r . %%d in (Debug,.vs) do @if exist "%%d" rd /s/q "%%d"

Эта версия должна работать на основе того, что я вижу на других страницах здесь, но это не так:

for /d /r . %%d in (Debug,.vs) do ^
   @if exist "%%d" rd /s/q "%%d"

Его выход

C:\Project1>for / %d in (Debug .vs) do    @if exist "%d" rd /s/q "%d" 

C:\Project1>   @if exist "C:\Project1\Debug" rd /s/q "C:\Project1\Debug" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>   @if exist "C:\Project1\.vs" rd /s/q "C:\Project1\.vs" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>for / %d in (Debug .vs) do    @if exist "%d" rd /s/q "%d" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>   @if exist "C:\Project1\Debug" rd /s/q "C:\Project1\Debug" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>   @if exist "C:\\.vs" rd /s/q "C:\Project1\.vs" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

...

Я также пробовал вариант без ^:

for /d /r . %%d in (Debug,.vs) do (
   @if exist "%%d" rd /s/q "%%d"
)

Это на самом деле удаляет вещи, но также дает странный вывод:

C:\Project1>for / %d in (Debug .vs) do    @if exist "%d" rd /s/q "%d" 

C:\Project1> ()

C:\Project1> ()

C:\Project1> ()

C:\Project1> ()

...

Просто отключив (), я получаю «Синтаксис команды неверен».

Ответы [ 2 ]

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

Вы можете вставить строки в приглашении CMD, которые длиннее, чем отображается, просто прокручивает вправо (или влево в зависимости от того, как вы их просматриваете)

Однако вы используете %% в своемимена переменных, что означает, что вы должны запускать это внутри скрипта CMD / BAT.Что позволит использовать строки еще длиннее.

Так что все должно быть в порядке:

REM Single Line:
FOR /R %%D in (Debug,.vs) DO @( ECHO Checking: "%%~D" &  IF EXIST "%%~D" ( ECHO. Found! - Removing: "%%~D" ... & RD /S /Q "%%~D" ) )

или меньше, если вам действительно это нужно:

REM Even Smaller Single Line:
FOR /R %%D in (Debug,.vs) DO @(IF EXIST "%%~D" (RD /S/Q "%%~D"))

Меньше - игнорировать неошибки каталога

REM Even Smaller Single Line:
FOR /R %%D in (Debug,.vs) DO @(RD /S/Q "%%~D") 2>Nul

Самая маленькая одиночная строка, но вывод будет выглядеть довольно грязно

REM Even Smaller Single Line:
FOR /R %%D in (Debug,.vs) DO (RD/S/Q "%%D")

Теперь, если по какой-либо причине вы хотите сделать этоКак можно меньше, и вы работаете внутри сценария cmd, вы можете помещать возврат каретки после каждого открытия и закрытия Paren, и вы можете помещать возврат каретки между терминами в ваших критериях.

Многострочный:

FOR /R %%D in (
 Debug
 .vs
) DO @(
 ECHO Checking: "%%~D" 
 IF EXIST "%%~D" (
  ECHO. Found! - Removing: "%%~D" ...
  RD /S /Q "%%~D"
 )
)

По какой-либо причине почти никто не выполняет вышеперечисленные критерии, но это полностью допустимый параметр.

Кратчайшие строки в многострочном файле, которые являются возможными:

@ECHO OFF
FOR /R %%D in (
Debug
.vs
) DO (
RD /S /Q "%%~D"
)

And Are в версиях CLI CMD Если вы доверяете, вы можете вставить больше, чем видите:

FOR /R %D in (Debug,.vs) DO @( ECHO Checking: "%~D" &  IF EXIST "%~D" ( ECHO. Found! - Removing: "%~D" ... & RD /S /Q "%~D" ) )

И меньше, если не можете:

FOR /R %D in (Debug,.vs) DO @(IF EXIST "%~D" (RD/S/Q "%D")

И как я уже говорил, ВЫ МОЖЕТЕ использовать тот же методВ случае возврата каретки для прямой вставки в приглашение CMD, как правило, люди этого не делают, потому что вероятность вставки в приглашение cmd с большей вероятностью будет разбита, но код вашего требования довольно прост, поэтому его можно полностью вставить вПодсказка CMD напрямую:

Самая маленькая многострочная версия CMD-Prompt оригинала:

@ECHO OFF
FOR /R %D in (
Debug
.vs
) DO @(
RD /S/Q "%~D"
)

Кроме того, вам нужно использовать FOR /R %D, только когда выwrite FOR /D /R . %D CMD просто проигнорирует / D и изменит синтаксис / R, аналогично.не требуется, потому что подразумевается, что вы используете ., если не выбран базовый каталог.

Если оставить ненужные символы, вы сэкономите три лишних символа:)

FOR /Rавтоматически просматривает дерево каталогов, в то время как /D приходится делать это, используя подстановочный знак, в то время как добавление /R после /D по существу заставляет цикл For игнорировать /D и использовать вместо этого синтаксис /Rи отличается только в том случае, если вы используете подстановочные знаки (которых у вас нет).

Более того:

Как я уже упоминал в комментариях к другому члену, существуют более целесообразные методы поиска каталогов с.vs или debug с использованием DIR, который будет намного быстрее их перечислять, и FindStr, который будет намного быстрее находить их, чем тестировать, если они существуют.

У меня не было временивчера вечером из-за ненужной дискуссии с этим участником о том, почему добавление /D к моим перечисленным командам не было необходимым, однако, я помещу первый черновик из них здесь.

Это наименьшая максимальная требуемая длина, возможная без подстановки переменных из манжеты (длина 25 символов), и может быть запущена в строке CMD:

Наименьшая CMD-LINE FindStr v offманжета без подстановки (Len 25):

@ECHO OFF
FOR /F "tokens=*" %A IN (
'DIR
  /AD/B/S
^|
 FINDStr /I /R
  /C:"\\\.vs$"
  /C:"\\debug$"
') DO @( RD/S/Q "%A")

На самом деле, есть еще одна вещь, которую мы можем сделать, которая приводит к тому же максимальному размеру, что и предыдущая команда (Len 14), которая неТехнически не используя подстановку переменных, мы можем обернуть ее в другой цикл FOR / F.

Дополнительный цикл только печатает и может быть настроен так, чтобы ничего не делать, что сделает его быстрее, кроме внутреннего или внешнего цикла.можно сделать удаление (я выбрал внутренний цикл)

Наименьший CMD-LINE FindStr v Использование второго цикла без переменной Подстановка (Len 14):

@ECHO OFF
FOR /F %a IN (
'FOR /F
"UseBackQ"
%A IN (
`DIR
/AD/B/S
^^^|
FINDStr /I /R
/C:"\\\.vs$"
/C:"\\debug$"
`^) DO @(
ECHO."%A"
RD /Q/S "%A"
^) ') DO @(
ECHO.Gone: %a)

Если мы хотим попасть в Переменную Подстановку, то минимальная длина строки, вероятно, составляет около 10 символов.

Опубликует это позже

1 голос
/ 21 июня 2019

Ваш последний код, for /r . %%d in (Debug,.vs) do @if exist "%%d" rd /s/q "%%d", не самый эффективный метод.Он добавляет \Debug и \.vs в каждый подкаталог текущего каталога, а затем передает каждый из них, (2 на каждый подкаталог) , через команду If Exist, прежде чем вводить команду RD для тех, которыесуществовать.Нет конкретного утверждения, чтобы определить, является ли то, что существует, каталогомНапример, файл без расширения с именем debug в настоящее время будет передаваться вашей команде RD.Это можно легко исправить, добавив обратную косую черту, for /r . %%d in (Debug,.vs) do @if exist "%%d\" rd /s/q "%%d".Однако это добавило бы к вашей команде еще один символ, который можно было бы отменить, удалив текущую спецификацию каталога по умолчанию для опции For /R, , как объяснено в ответе Бена ,например, for /r %%d in (Debug,.vs) do @if exist "%%d\" rd /s/q "%%d".

Теперь вы показали нам, что ваш максимум находится где-то между 60 и 62 символами на строку, (начальная длина строки была 63, последняя - 60) , я подумал, что предоставлю пример кода Dir:

@For /F "Delims=" %%A In (
 'Dir /B/S/AD Debug .vs 2^>NUL'
)Do @RD /S/Q "%%A" 2>NUL

Использование FindStr также может , как предложено в комментарии Бена , предоставьте альтернативное решение:

@For /F "Delims=" %%A In (
 'Dir /B/S/AD 2^>NUL^|FindStr /I "\\Debug$ \\\.vs$"'
)Do @RD /S/Q "%%A" 2>NUL

Следует отметить одну тривиальную вещь: вполне возможно, что подкаталог с именем Debug или .vs может существовать как подкаталоглибо Debug, либо .vs. Кажется немного глупым потенциально передавать родного брата, принадлежащего уже удаленному подкаталогу, другому процессу удаления .Чтобы предотвратить это, , хотя скорость не проверена, я не вижу, чтобы она была намного медленнее, если вообще, по сравнению с моим предыдущим примером , ее можно было бы передать через вторую команду FindStr:

@For /F "Delims=" %%A In ('
 Dir /B/S/AD-L-S 2^>NUL^|^
 FindStr /I "\\Debug$ \\\.vs$"^|^
 FindStr /IV "\\Debug\\ \\\.vs\\"
')Do @RD /S/Q "%%A" 2>NUL

В приведенном выше примере также добавлена ​​дополнительная защита для фильтрации любых потенциальных системных каталогов и точек повторной обработки.

Хотя все вышеперечисленные решения явно длиннее 60 символов, я сохранилвсе они находятся в пределах этого максимального предела линии, пытаясь сохранить баланс и удобочитаемость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...