嵌套批处理 for 循环

Posted

技术标签:

【中文标题】嵌套批处理 for 循环【英文标题】:Nested batch for loops 【发布时间】:2011-05-19 01:34:34 【问题描述】:

以下嵌套的 for 循环让我发疯(在 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、调用语句和诸如此类的东西,但我从来没有让内部循环正常工作。我知道我可以通过子例程调用替换内部循环,但是必须有一种方法可以使它与嵌套循环一起使用。

【问题讨论】:

【参考方案1】:

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

@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 的观察,即如果循环中的变量扩展出现在括号内(即使没有延迟扩展),它们也会起作用。

【讨论】:

嗨,我用了你的例子,但它会在最后一个陡峭的地方打印 %%b 而不是 %%a,我在内部循环中只使用 FOR %%a in (%A%) 解决了这个问题 @JuanAntonioOrozco 您可能已经观察到预期的行为。我编辑了我的答案以澄清循环应该打印的内容。【参考方案2】:

因为没有人提及,这里是使用批处理子程序和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 不是很流行,但批处理文件最初设计为使用标签进行控制流。带括号的控制结构语法是后来添加的,这个问题是它分解的一个例子。这个问题很适合批处理子程序。

【讨论】:

【参考方案3】:

如果你使用pushd !CTD!popd,让FOR /R默认使用当前目录呢?

【讨论】:

我会接受这个解决方案,因为它解决了我的示例上下文中的问题。它真的很聪明:-) 这是一种以不同方式解决特定问题的解决方法。它没有解释如何正确嵌套 for 循环(即不回答问题)。我想用不同的用例嵌套for循环,在这种情况下,这种解决方法不能解决问题,而是通过谷歌搜索“批量嵌套for循环”来到这里。 -1 来自我。【参考方案4】:

不明显!是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 ....  

不将abc设置为delims,而是!c、har

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

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

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

【讨论】:

抱歉,但我看不出您的回复如何帮助我解决我的问题,因为它只告诉我什么不起作用。另外,我在我的问题中已经提到我知道用子例程替换内部循环的可能性,但我的问题是如何使嵌套循环工作。 抱歉,我想您只能使用 Ben Voigt 的 PUSHD 解决方案。扩展似乎是不可能的,因为内部循环的路径只扩展了一个,在第一个括号的开头,【参考方案5】:

引用 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

【讨论】:

【参考方案6】:

根据 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。)

【讨论】:

此答案将包括不在%TESTDIRS% 中的目录。正如问题中所述,/R src\test\resources\testsuite\fast %%f 有效,这是set CTD=%TD%\%%d 的预期结果,因此问题不太可能是对树的行走方式的误解。

以上是关于嵌套批处理 for 循环的主要内容,如果未能解决你的问题,请参考以下文章

带计数器的多处理嵌套 for 循环

在批处理文件中,如果满足一个条件而不是周围的 for 循环,如何突破嵌套的 if 语句?

python扩展库numpy中函数meshgrid()的使用[当你想要两个for循环嵌套处理时,就该想到它]

解析嵌套完成处理程序

C - for循环和循环嵌套

C语言中:两个for循环嵌套使用有什么作用?