Batch file 为/L循环嵌套并退出循环的批处理文件
这段代码没有像我期望的那样通过for循环。我试着做这样的事,但没用。有什么建议吗 编辑 当可执行文件完成运行时,ERRORLEVEL不是1Batch file 为/L循环嵌套并退出循环的批处理文件,batch-file,for-loop,nested,Batch File,For Loop,Nested,这段代码没有像我期望的那样通过for循环。我试着做这样的事,但没用。有什么建议吗 编辑 当可执行文件完成运行时,ERRORLEVEL不是1 SETLOCAL ENABLEDELAYEDEXPANSION set list=A B C D E FOR %%a IN (%list%) DO ( start %%a.exe > ouput_%%a.txt echo 120, 30 second loops = 60 min FOR /L %%i IN (1,1,120)
SETLOCAL ENABLEDELAYEDEXPANSION
set list=A B C D E
FOR %%a IN (%list%) DO (
start %%a.exe > ouput_%%a.txt
echo 120, 30 second loops = 60 min
FOR /L %%i IN (1,1,120) DO (
REM pause for 30 seconds
ping 1.1.1.1 -n 1 -w 30000 > nul
echo find the running executable
tasklist | findstr %%a.exe > nul
REM !ERRORLEVEL!
REM exit the script if no executable is found (i.e it has run successfully)
if !ERRORLEVEL! equ 1 goto success
)
REM kill executable if we haven't exited yet
taskkill /f /im %%a.exe
:success
)
在
for
循环中执行goto
命令会中断循环迭代。这适用于所有嵌套的for
循环
但是,您可以做的是将内部for
循环移动到一个子例程中(使用call
调用它)。此循环可通过goto
命令终止,但从子程序返回后,循环的剩余(外部)不受影响,并继续迭代
SETLOCAL ENABLEDELAYEDEXPANSION
set list=A B C D E
FOR %%a IN (%LIST%) DO (
start %%a.exe > ouput_%%a.txt
REM 120, 30 second loops = 60 min
call :innerloop %%a
REM kill executable if we haven't exited yet
taskkill /f /im %%a.exe
)
goto :eof
:innerloop
FOR /L %%i IN (1,1,120) DO (
REM pause for 30 seconds
ping 1.1.1.1 -n 1 -w 30000 > nul
REM find the running executable
tasklist | findstr %%a.exe > nul
REM !ERRORLEVEL!
REM exit the script if no executable is found (i.e it has run successfully)
if %ERRORLEVEL% equ 1 goto :next
)
:next
goto :eof
在此,我将内部for
循环移动到一个子例程:SUBLOOP
,该子例程由调用:SUBLOOP%%a.exe
从外部for
循环调用,将当前值传递给它进行处理(可执行文件%%a.exe
)<代码>错误级别
在终止时传输到调用例程。从
:SUBLOOP
返回外部for
循环后,检查ERRORLEVEL
是否为零,如果为零,则终止当前迭代的可执行文件的进程。&&
是一个条件命令分隔符,只有在第一个命令成功时,即清除了ERRORLEVEL
时,才执行第二个命令。注意外部
for
循环后的exit/B
命令,这是在外部循环完成后不无意执行子循环
部分所必需的
注意:goto
不会立即终止for
循环迭代;事实上,每个挂起的迭代仍然以静默方式计数,但是不再执行for
主体的命令。因此,具有大量迭代的循环可能需要相当长的时间才能继续批处理执行。谢谢@foxidrive此外,如果
goto
目标标签被放置在for
主体中,则循环完全完成后,执行将在该点继续。然后,该点之后的任何代码都将被视为“正常”代码,而不是正文的部分。在编辑的代码中,您需要使用!错误等级代码>而不是%ERRORLEVEL%
!此外,您根本不是在查询!错误等级!在“循环”的外部
。您可以测试call:innerloop%%a | | taskkill/f/im%%a.exe
是否有效(这意味着taskkill
仅在call
返回非零ERRORLEVEL
时才会执行)。如果一个可执行文件仍在运行,则此代码会导致可执行文件彼此重叠。抱歉,最后一件事。添加/WAIT
开关时,输出%%a.txt
中没有任何文本。如何解决此问题?为什么我需要/WAIT
?存在内部for循环是为了在一个小时过去或可执行文件完成执行之前不允许外部循环运行@aschipfl@aschipflgoto
命令不会立即终止for循环-它会静默地计算每一个尚未通过的过程。尝试一个for循环
计数高达1000万次,并在达到5000次时使用goto来查看发生了什么。@aschipfl是的,它停止处理命令-但您编写的循环会立即终止迭代
,它不会,因为长循环可能会在继续批处理脚本之前再运行15分钟等等。您的描述应该改写为循环可能需要相当长的时间才能继续批处理。有一些技术可以立即退出for循环
,但这不是其中之一。
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
set list=A B C D E
FOR %%a IN (%list%) DO (
start %%a.exe > ouput_%%a.txt
echo 120, 30 second loops = 60 min
REM kill executable if we haven't exited yet
call :SUBLOOP %%a.exe && taskkill /f /im %%a.exe
)
exit /B
:SUBLOOP
FOR /L %%i IN (1,1,120) DO (
REM pause for 30 seconds
timeout /T 30 /NOBREAK > nul
echo find the running executable
tasklist | findstr /I /B "%~1" > nul
REM !ERRORLEVEL! is 0 if found and 1 otherwise
REM exit the script if no executable is found
REM (i.e it has run successfully)
if !ERRORLEVEL! equ 1 goto :EOF
)
exit /B 0