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