Вложенная партия для петель - PullRequest
20 голосов
/ 02 декабря 2010

Следующие вложенные циклические циклы сводят меня с ума (в Windows 7):

@echo off
SetLocal EnableDelayedExpansion

set TESTDIRS=fast mid slow
set TD=src\test\resources\testsuite

for %%d in (%TESTDIRS%) do (
    set CTD=%TD%\%%d
    echo CTD: !CTD!
        REM Echos the expected path
    echo CTD: %CTD%
        REM Echos nothing -- understandable

    for /R !CTD! %%f in (*.fs) do (echo %%f)
        REM Echos nothing -- why?
    for /R src\test\resources\testsuite\fast %%f in (*.fs) do (echo %%f)
        REM Echos expected files
)

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

Ответы [ 4 ]

23 голосов
/ 08 декабря 2010

Просто чтобы привести пример вложенного цикла, который работает:

@echo off
SetLocal

set B=alpha beta gamma
set A=eins zwo

FOR %%b in (%B%) do (
  FOR %%a in (%A% %%b) DO (
    echo %%b -^> %%a
  )
)

Выход (по крайней мере, в Windows 7):

alpha -> eins
alpha -> zwo
alpha -> alpha
beta -> eins
beta -> zwo
beta -> beta
gamma -> eins
gamma -> zwo
gamma -> gamma

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

12 голосов
/ 04 марта 2015

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

@echo off

set TESTDIRS=fast mid slow
set TD=src\test\resources\testsuite

for %%d in (%TESTDIRS%) do call :process_testdir %%d
goto :eof

:process_testdir
set CTD=%TD%\%1
echo CTD: %CTD%
    REM Echos the expected path

for /R %CTD% %%f in (*.fs) do (echo %%f)
    REM Echos as expected

goto :eof

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

11 голосов
/ 02 декабря 2010

Что, если вы использовали pushd !CTD! и popd, и позволили FOR /R по умолчанию использовать текущий каталог?

5 голосов
/ 02 декабря 2010

Это не очевидно! Это специальный разбор FOR !
Команда FOR анализируется непосредственно после фазы перехода / специального символа (для определения скобок), но в результате вы не можете использовать задержанное или %% var расширение в качестве параметров.

FOR %%a in (%%%%B) do (
  FOR %%a in (1) DO ( <<< this %%a will not replaced with %%B
      echo %%a - shows 1, because %%a is the name of the inner variable
      echo %%B - doesn't work
  )
)

А также это не может работать:

set chars=abc
FOR /F "delims=!chars!" %%N in (bla) DO ....  

не устанавливает a , b и c в качестве разделителей, но ! , c , ч , a и r вместо.

РЕДАКТИРОВАТЬ: В скобках отложенное расширение работает, как и ожидалось:

set var=C:\temp
For %%a in (!var!) DO echo %%a

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

...