1

Я пытаюсь преобразовать многострочный скрипт

@echo off

for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (
  pushd "%%D"
  for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul
  popd
  rd /s /q "%%D"
)
exit

в одну строку, чтобы зарегистрировать его как пункт контекстного меню. Насколько я понимаю, эквивалентная однострочная команда будет такой:

@echo off && for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (pushd "%%D" && for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul && popd && rd /s /q "%%D") && exit

... но это дает результаты, отличные от оригинального сценария.

Замена && на & дает третий другой результат, но, насколько я знаю, мне все равно понадобится && в этом случае.

Что я могу делать не так?

1 ответ1

1

Оказывается, что for … do это «жадный».  (Я не помню, чтобы знал об этом раньше, и это, кажется, не документировано в for /? )

Вот что я имею в виду:

Рассмотрим скрипт cow1.bat:

@echo off
for %%a in (how now brown) do echo %%a
echo cow

Довольно тривиально.  При запуске выводит

how
now
brown
cow

как мы могли догадаться.

Рассмотрим скрипт cow2.bat:

@echo off
for %%a in (how now brown) do echo %%a & echo cow

То же самое, за исключением строк 2 и 3, объединенных символом & .  Угадай, что!?  При запуске выводит

how
cow
now
cow
brown
cow

Это интерпретируется как если бы это было

@echo off
for %%a in (how now brown) do (echo %%a & echo cow)

(Изменение & на && не имело никакого эффекта.)  В (для меня) больший сюрприз,

@echo off
for %%a in (how now brown) do (echo %%a) & echo cow

также функционировал так же, как cow2 .  Я должен был использовать

@echo off
(for %%a in (how now brown) do echo %%a) & echo cow

чтобы получить оригинальное поведение cow1 .


Как это влияет на ОП?

for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul && popd && rd /s /q "%%D"

аналогично cow2: если %%D (каталог, в который мы только что pushd ) - это beatles , то приведенный выше фрагмент кода делает это:

move "george" "..\beatles - george" >nul    &&    popd    &&    rd /s /q "beatles"
move "john"   "..\beatles - john"   >nul    &&    popd    &&    rd /s /q "beatles"
move "paul"   "..\beatles - paul"   >nul    &&    popd    &&    rd /s /q "beatles"
move "ringo"  "..\beatles - ringo"  >nul    &&    popd    &&    rd /s /q "beatles"

(пробелы добавлены для ясности).  Так что движется первый файл george а затем popd «ИНГ из каталога beatles и удалить его, оставляя другие файлы , которые будут пожинать в Roomba.

Рекомендация (TL; DR)

Пытаться

for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (pushd "%%D" && (for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul) && popd && rd /s /q "%%D")
                                                                              ↑                                                   ↑
 

Тривиальный вопрос:

Зачем нам нужна * в подкоманде dir /b /s /ad * ?

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .