批处理文件嵌套/ L循环并退出它们 [英] Batch File Nested For /L Loops and Exiting them
问题描述
SETLOCAL ENABLEDELAYEDEXPANSION
set list = ABCDE
FOR %% a IN(%list%)DO(
start %% a .exe> ouput _ %% a.txt
echo 120,30 second loop = 60 min
FOR / L %% i IN(1,1,120)DO(
REM暂停30秒
ping 1.1.1.1 -n 1 -w 30000> nul
echo找到正在运行的可执行文件
tasklist | findstr %% a.exe> nul
REM !ERRORLEVEL!
如果没有找到可执行文件,REM退出脚本(即它已经成功运行)
if!ERRORLEVEL!equ 1 goto success
)
REM 't已退出
taskkill / f / im %% a.exe
:success
)
这段代码并没有像我期望的那样通过for循环。我试图做这样的事情如何如何打破内部循环在嵌套循环批处理脚本,但无济于事。任何建议?
$ b
编辑
当可执行文件完成时,ERRORLEVEL不是1运行。
SETLOCAL ENABLEDELAYEDEXPANSION
set list = ABCDE
FOR %% IN(%LIST %)DO(
start %% a.exe>输出_ %% a.txt
REM 120,30秒循环= 60分钟
调用:innerloop %% a
REM杀死可执行文件,如果我们还没有退出
taskkill / f / im %% a.exe
)
goto:eof
:innerloop
FOR / L %%我IN(1,1,120)DO(
REM暂停30秒
ping 1.1.1.1 -n 1 -w 30000> nul
REM找到正在运行的可执行文件
任务列表| findstr %% a.exe> nul
REM!ERRORLEVEL!
如果找不到可执行文件,REM将退出脚本(即已成功运行)
如果%ERRORLEVEL% 1 goto:next
)
:next
goto:eof
中为
循环执行 goto
命令会破坏循环迭代。对于全部嵌套 for
循环。 然而,你可以做什么将循环内部的循环移动到一个子例程中(使用
call
调用它)。这个循环可以由 goto
命令结束,但是在从子例程返回之后,剩下的(外部的)代表
循环不受影响,并继续迭代。
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
set list = ABCDE
FOR %% a IN(%list%)DO(
start %% a.exe>输出_ %% a.txt
回显120,30秒循环= 60 min
如果我们还没有退出,则可以杀死可执行文件
call:SUBLOOP %% a.exe&& taskkill / f / im %% a.exe
)
退出/ B
:SUBLOOP
FOR / L %% i IN(1,1,120)DO(
REM暂停30秒
超时/ T 30 / NOBREAK > nul
echo找到正在运行的可执行文件
tasklist | findstr / I / B%〜1> nul
REM!ERRORLEVEL!为0,否则为1
如果找不到可执行文件,REM退出脚本
REM(即它已经成功运行)
if!ERRORLEVEL!equ 1 goto:EOF
)
exit / B 0
这里我把循环的内部移到了一个子程序
中:SUBLOOP
,它从前面的代码段调用调用:SUBLOOP %% a.exe
,将当前值传递给进程(可执行文件 %% a.exe
)从外部为
循环。 ERRORLEVEL
在终止时被传送到调用例程。
从:SUBLOOP
返回在循环的外部中,检查
ERRORLEVEL
是否为零,如果是,则检查当前进程迭代的可执行文件被终止。 &&
是一个条件命令分隔符,它只有在第一个命令成功的时候才执行第二个命令,也就是说,如果 ERRORLEVEL
被清除。
在循环的外部之后,注意
出口/ B
这是在外循环完成后无意执行 SUBLOOP
部分所必需的。
注意:
goto
不立即终止循环迭代的;实际上,每个挂起的迭代仍然被默默地计算在内,但是没有更多的
for
body命令被执行。因此,在批处理执行继续之前,具有大量迭代的循环可能需要相当长的时间。谢谢@foxidrive这个有用的信息 a>!
此外,如果 goto
目标标签位于 for
主体内,执行循环完成后,继续执行。之后的任何代码将被视为正常,而不是 body的部分。
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
)
This code doesn't go through the for loops as I expect them to. I tried to do something like this How to break inner loop in nested loop batch script , but to no avail. Any advice?
EDIT
ERRORLEVEL is not 1 when an executable has finished running.
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
Executing the goto
command within a for
loop breaks up the loop iteration. This is true for all nested for
loops.
However, what you can do is moving your inner for
loop into a sub-routine (call it using call
). This loop can be terminated by a goto
command, but after returning from the sub-routine, the remaining (outer) for
loop is not affected and continues iteration.
@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
Herein I moved the inner for
loop into a sub-routine :SUBLOOP
, which is called from its former code section by call :SUBLOOP %%a.exe
, passing the current value to process (the executable %%a.exe
) from the outer for
loop to it. ERRORLEVEL
is transferred to the calling routine upon termination.
After returning from :SUBLOOP
back to the outer for
loop, it is checked whether or not ERRORLEVEL
is zero, and if so, the process of the currently iterated executable is killed. The &&
is a conditional command separator which executes the second command only if the first one succeeded, that is, if ERRORLEVEL
is cleared.
Note the exit /B
command after the outer for
loop which is necessary to not execute the SUBLOOP
section unintentionally after the outer loop has been completed.
Note:
goto
does not terminate the for
loop iteration immediately; in fact every pending iteration is still counted silently, but no more commands of the for
body are executed. A loop with a huge number of iterations can therefore take a considerable amount of time before batch execution continues. Thank you @foxidrive for this useful information!
Moreover, if the goto
target label is placed within the for
body, execution continues at that point after total completion of the loop. Any code following that point is then treated as "normal" one not part of a for
body.
这篇关于批处理文件嵌套/ L循环并退出它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!