嵌套批处理循环

时间:2010-12-02 10:59:45

标签: windows loops batch-file for-loop nested

以下嵌套的for-loop让我很生气(在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,call-statements等等,但我从来没有让内循环工作。我知道我可以通过子程序调用替换内部循环,但必须有一种方法可以使它与嵌套循环一起使用。

6 个答案:

答案 0 :(得分:22)

举一个有效的嵌套循环的例子:

@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

这支持了jeb的观察,即如果它们出现在括号内(即使没有延迟扩展),循环中的变量扩展也可以工作。

答案 1 :(得分:12)

因为没有人提到它,所以这里是使用批处理子程序和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不是很受欢迎,但批处理文件最初设计用于控制流程的标签。后面添加了括号中的控制结构语法,这个问题就是它出现故障的一个例子。这个问题非常适合批处理子程序。

答案 2 :(得分:10)

如果您使用pushd !CTD!popd,并且FOR /R默认使用当前目录怎么办?

答案 3 :(得分:5)

这不明显!这是 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 设置为delims,但 c < / strong>, h a r

编辑:在括号内,延迟扩展确实按预期工作:

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

我希望你必须使用一个函数来解决你的问题。

答案 4 :(得分:1)

引用Malte Schwerhoff的答案

如果您不想重复B,则只需添加“ if”语句

@echo off
SetLocal

set B=alpha beta gamma
set A=eins zwo

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

输出:

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

答案 5 :(得分:0)

根据FOR帮助,FOR /R“步行以[drive:] path为根的目录树,在树的每个目录中执行FOR语句。”

可能出现的问题是“行走”一词。在我看来,直到有人迈出第一步才走,如果不走,就不会走。由于在这种情况下,漫游从目录“ fast”开始,并且没有子目录,因此第一步是不可能的。

但是,如果将第二个FOR更改为:

for /R !CTD!\..\ %%f in (*.fs) do (echo %%f)

然后回显的结果是:

CTD: src\test\resources\testsuite\fast
CTD:
C:\FORTEST\src\test\resources\testsuite\fast\F1.fs
C:\FORTEST\src\test\resources\testsuite\mid\F2.fs
C:\FORTEST\src\test\resources\testsuite\slow\F3.fs
C:\FORTEST\src\test\resources\testsuite\fast\F1.fs
CTD: src\test\resources\testsuite\mid
CTD:
C:\FORTEST\src\test\resources\testsuite\fast\F1.fs
C:\FORTEST\src\test\resources\testsuite\mid\F2.fs
C:\FORTEST\src\test\resources\testsuite\slow\F3.fs
C:\FORTEST\src\test\resources\testsuite\fast\F1.fs
CTD: src\test\resources\testsuite\slow
CTD:
C:\FORTEST\src\test\resources\testsuite\fast\F1.fs
C:\FORTEST\src\test\resources\testsuite\mid\F2.fs
C:\FORTEST\src\test\resources\testsuite\slow\F3.fs
C:\FORTEST\src\test\resources\testsuite\fast\F1.fs

这是OP在寻找“ FOR”吗?如果是这样,那是因为现在有一个可以从其递归的地方,那就是父目录。

(注意:在此测试中,快,慢,慢目录分别包含一个文件,分别为F1.fs,F2.fs和F3.fs。)