批处理脚本中嵌套标签的奇怪行为
Weird behavior for nested labels in batch script
这是批处理程序:
@echo off
SETLOCAL EnableDelayedExpansion
set /a incr=0
set arg1=%1
del test_output.csv > NUL 2>&1
del test_output.log > NUL 2>&1
set startTime=%time%
for /d %%i in ("%cd%\*") do call :run_test "%%i"
.\log_parser.exe
type test_output.csv
echo Start Time: %startTime%
echo Finish Time: %time%
exit /B
:run_test
if not "%~nx1" == "shared" (
echo Test: %~nx1
cd %1
del pass_fail_output.csv > NUL 2>&1
echo Running...
cd temp_root_fs
start application.exe
set /a incr=0
:while1
tasklist /fi "IMAGENAME eq application.exe" 2>NUL | find /i /n "application.exe">NUL
if "%ERRORLEVEL%"=="0" (
if %incr% leq 60 (
echo Still running...
timeout /t 1 > NUL 2>&1
set /a incr+= 1
goto :while1
)
echo Test timed out...
taskkill /im application.exe /f
)
echo Test completed...
cd logs
.\pass_fail_parser.exe
type log.log >> ..\..\..\test_output.log
copy pass_fail_output.csv ..\..\
cd ..\..\
)
echo Cleaning...
rmdir /S /Q temp_root_fs
cd ..
)
这是我的预期执行:
- 遍历文件夹
- 运行 申请
- 等待 60 秒,然后在 60 秒后终止应用程序,或者在应用程序完成后继续
- 执行其他一些操作以将日志消息移植到整个日志文件中
第一个循环工作正常,但这是我执行它时当前输出的样子:
Test: test1
Initializing...
Running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Test completed...
1 file(s) copied.
Cleaning...
我知道这不能正常工作,因为我还有 3 个文件夹用于测试,所以它应该继续到其他文件夹,但不知何故它似乎提前脱离了 for 循环。
我读过 /I
option 据说可以防止 goto 跳出 iff 和 do 循环,但我不完全确定它是如何工作的(我尝试将它添加为参数,但它要么出错,要么似乎什么也没做)。
如有任何帮助,我们将不胜感激!
:run_test
if not "%~nx1" == "shared" (
echo Test: %~nx1
cd %1
del pass_fail_output.csv > NUL 2>&1
echo Running...
cd temp_root_fs
start application.exe
set /a incr=0
CALL :while1
echo Test completed...
cd logs
.\pass_fail_parser.exe
type log.log >> ..\..\..\test_output.log
copy pass_fail_output.csv ..\..\
cd ..\..\
)
echo Cleaning...
rmdir /S /Q temp_root_fs
cd ..
)
GOTO :EOF
:while1
tasklist /fi "IMAGENAME eq application.exe" 2>NUL | find /i /n "application.exe">NUL
if "%ERRORLEVEL%"=="0" (
if %incr% leq 60 (
echo Still running...
timeout /t 1 > NUL 2>&1
set /a incr+= 1
goto :while1
)
echo Test timed out...
taskkill /im application.exe /f
)
GOTO :EOF
在你的代码中,if not "%~nx1" == "shared" (
到最后的)
是一个code block
。代码块中不允许使用标签。当 if
语句为 parsed
时,值 %var%
被当时那些变量的值替换,而不是由于块内执行的操作而导致的更改。当心
以上代码将:while1
循环转换为由CALL :while1
调用的内部子程序(冒号是必需的表示调用是内部子程序标签)
注意 GOTO :EOF
语句。这些将执行转移到物理文件末尾(冒号又是 required)首先是防止执行从 :run_test
进入 :while1
流通。第二个是在 :while1
例程完成时强制 return 到 CALL :while1
之后的语句。 :while1
例程可以放在批处理主线中的 any goto
语句之后(即 not a goto
在一个代码块内)。
这是批处理程序:
@echo off
SETLOCAL EnableDelayedExpansion
set /a incr=0
set arg1=%1
del test_output.csv > NUL 2>&1
del test_output.log > NUL 2>&1
set startTime=%time%
for /d %%i in ("%cd%\*") do call :run_test "%%i"
.\log_parser.exe
type test_output.csv
echo Start Time: %startTime%
echo Finish Time: %time%
exit /B
:run_test
if not "%~nx1" == "shared" (
echo Test: %~nx1
cd %1
del pass_fail_output.csv > NUL 2>&1
echo Running...
cd temp_root_fs
start application.exe
set /a incr=0
:while1
tasklist /fi "IMAGENAME eq application.exe" 2>NUL | find /i /n "application.exe">NUL
if "%ERRORLEVEL%"=="0" (
if %incr% leq 60 (
echo Still running...
timeout /t 1 > NUL 2>&1
set /a incr+= 1
goto :while1
)
echo Test timed out...
taskkill /im application.exe /f
)
echo Test completed...
cd logs
.\pass_fail_parser.exe
type log.log >> ..\..\..\test_output.log
copy pass_fail_output.csv ..\..\
cd ..\..\
)
echo Cleaning...
rmdir /S /Q temp_root_fs
cd ..
)
这是我的预期执行:
- 遍历文件夹
- 运行 申请
- 等待 60 秒,然后在 60 秒后终止应用程序,或者在应用程序完成后继续
- 执行其他一些操作以将日志消息移植到整个日志文件中
第一个循环工作正常,但这是我执行它时当前输出的样子:
Test: test1
Initializing...
Running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Test completed...
1 file(s) copied.
Cleaning...
我知道这不能正常工作,因为我还有 3 个文件夹用于测试,所以它应该继续到其他文件夹,但不知何故它似乎提前脱离了 for 循环。
我读过 /I
option 据说可以防止 goto 跳出 iff 和 do 循环,但我不完全确定它是如何工作的(我尝试将它添加为参数,但它要么出错,要么似乎什么也没做)。
如有任何帮助,我们将不胜感激!
:run_test
if not "%~nx1" == "shared" (
echo Test: %~nx1
cd %1
del pass_fail_output.csv > NUL 2>&1
echo Running...
cd temp_root_fs
start application.exe
set /a incr=0
CALL :while1
echo Test completed...
cd logs
.\pass_fail_parser.exe
type log.log >> ..\..\..\test_output.log
copy pass_fail_output.csv ..\..\
cd ..\..\
)
echo Cleaning...
rmdir /S /Q temp_root_fs
cd ..
)
GOTO :EOF
:while1
tasklist /fi "IMAGENAME eq application.exe" 2>NUL | find /i /n "application.exe">NUL
if "%ERRORLEVEL%"=="0" (
if %incr% leq 60 (
echo Still running...
timeout /t 1 > NUL 2>&1
set /a incr+= 1
goto :while1
)
echo Test timed out...
taskkill /im application.exe /f
)
GOTO :EOF
在你的代码中,if not "%~nx1" == "shared" (
到最后的)
是一个code block
。代码块中不允许使用标签。当 if
语句为 parsed
时,值 %var%
被当时那些变量的值替换,而不是由于块内执行的操作而导致的更改。当心
以上代码将:while1
循环转换为由CALL :while1
调用的内部子程序(冒号是必需的表示调用是内部子程序标签)
注意 GOTO :EOF
语句。这些将执行转移到物理文件末尾(冒号又是 required)首先是防止执行从 :run_test
进入 :while1
流通。第二个是在 :while1
例程完成时强制 return 到 CALL :while1
之后的语句。 :while1
例程可以放在批处理主线中的 any goto
语句之后(即 not a goto
在一个代码块内)。