嵌套批处理 for 循环

发布于 2024-10-06 03:41:55 字数 635 浏览 1 评论 0原文

下面的嵌套 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、调用语句等,但我从未让内部循环正常工作。我知道我可以通过子例程调用来替换内部循环,但必须有一种方法可以使其与嵌套循环一起使用。

The following nested for-loop drives me mad (on 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
)

I tried various solutions involving disabling DelayedExpansion, call-statements and whatnot, but I never got the inner loop working. I know that I could replace the inner loop by a subroutine call, but there gotta be a way to make it work with nested loops.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

掐死时间 2024-10-13 03:42:59

根据 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”吗?如果是这样,那是因为现在有一个地方可以递归,那就是父目录。

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

According to FOR help, FOR /R "Walks the directory tree rooted at [drive:]path, executing the FOR statement in each directory of the tree."

What may be at issue is the word 'walk'. It seems to me that a walk doesn't occur until one takes the first step and if no step occurs then no walk occurs. Since in this case the walk begins in directory 'fast' and there are no subdirectories, no first step is possible.

However, if you change the second FOR to:

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

then the result echoed is:

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

Is that what OP was looking 'FOR'? If so, it would be because now there is someplace to recurse from, that being the parent dir.

(Note: in this test the dirs fast, mid, slow contained one file each, F1.fs, F2.fs and F3.fs, respectively.)

趁微风不噪 2024-10-13 03:42:54

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

Quote Malte Schwerhoff's Answer

If you don't want to repeat B, you can simply add "if" statement

@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
    )
  )
)

output:

alpha -> eins
alpha -> zwo
beta -> eins
beta -> zwo
gamma -> eins
gamma -> zwo
最丧也最甜 2024-10-13 03:42:50

这并不明显!就是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 设置为分隔符,而是设置 !,改为 char

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

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

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

It's not obvious! It's the special parsing of FOR!
A FOR command is parsed directly after the escape/special character phase (for detecting the parenthesis), but as a result you can't using delayed or %%var expansion as parameters.

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
  )
)

And also this can't work:

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

does not set a, b and c as delims, but !, c, h, a and r instead.

EDIT: Within the parentheses the delayed expansion does work as expected however:

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

I would expect that you have to use a function to solve your problem.

夜清冷一曲。 2024-10-13 03:42:44

如果您使用 pushd !CTD!popd,并让 FOR /R 默认使用当前目录会怎样?

What if you used pushd !CTD! and popd, and let FOR /R default to using the current directory?

挽梦忆笙歌 2024-10-13 03:42:38

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

Because nobody has mentioned it, here is the solution using batch subroutines and the CALL command.

@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

I know GOTO is not very popular, but batch files were originally designed to use labels for control flow. The parenthetized control structure syntax was added later, and this question is an example of where it breaks down. The problem lends itself well to batch subroutines.

梦境 2024-10-13 03:42:29

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

@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 的观察,即循环中的变量扩展如果出现在括号内,则可以工作(即使没有延迟扩展)。

Just to give an example of a nested loop that works:

@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
  )
)

The output (at least on Windows 7) is

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

This supports jeb's observation that variable expansion in loops works if they occur inside parenthesis (even without delayed expansion).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文