考虑一个名为 t.cmd 的命令脚本,它只包含以下两行:
@exit /b 123
@echo If you see this, THEN EXIT FAILED..
因此,该脚本只是将脚本执行过程的退出代码设置为123,并没有杀死cmd.exe。最后的 echo 确认退出实际上导致立即返回(它的输出不应该出现)。
现在执行这个脚本,然后打印出%errorlevel%:
>t.cmd
>echo %errorlevel%
123
到目前为止一切顺利:一切都完全符合预期。
但现在在一行中执行以上所有内容,使用 && 进行条件执行:
>t.cmd && echo %errorlevel%
123
我不希望这样:如果 t.cmd 真的以非 0 退出代码返回,那么它应该停止执行 &&(即回显)之后的所有内容。我们看到它打印的事实意味着它确实执行了。这到底是怎么回事?
如果在一行中执行上述所有操作,使用 ||对于条件执行:
>t.cmd || echo %errorlevel%
>
此行为也与我的预期相反(尽管它与上面的 && 行为一致)。
请注意,这种奇怪的行为仅适用于 bat 文件,但不适用于“原始命令”。
证明:考虑以下命令行交互,我尝试执行虚假命令 abcdef 而不是调用 t.cmd:
>abcdef
'abcdef' is not recognized as an internal or external command,
operable program or batch file.
>echo %errorlevel%
9009
>abcdef && echo %errorlevel%
'abcdef' is not recognized as an internal or external command,
operable program or batch file.
>abcdef || echo %errorlevel%
'abcdef' is not recognized as an internal or external command,
operable program or batch file.
9009
在这里,&& 和||立即查看失败的伪造命令的退出代码。
那么为什么 cmd 文件的行为不同?
已在 File redirection in Windows and %errorlevel% 中观察到 cmd.exe 中可能相关的错误
此外,我知道 ERRORLEVEL is not %ERRORLEVEL%
顺便说一句,上面的代码都是在 Win 7 Pro 64 位机器上执行的。我不知道其他版本的 Windows 的行为如何。
最佳答案
对t.bat
稍作修改如下:
@exit /b 123%~1
@echo If you see this, THEN EXIT FAILED..
想出下一个输出:
==>t.bat 1
==>echo %errorlevel%
1231
==>t.bat 2&echo %errorlevel%
1231
==>echo %errorlevel%
1232
==>cmd /V /C t.bat 3^&echo !errorlevel!
1233
==>echo %errorlevel%
0
==>cmd /V /C t.bat 4^&echo !errorlevel!^&exit /B !errorlevel!
1234
==>echo %errorlevel%
1234
==>
资源
- (
%~1
等特殊页面)Command Line arguments (Parameters) - (特殊页面)EnableDelayedExpansion
编辑启发EnableDelayedExpansion
:
==>cmd /v
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
==>t.bat 5&echo !errorlevel!
1235
==>echo %errorlevel%
1235
==>
编辑 2 启发(或混淆?)&&
和 ||
。将下一个代码片段保存为 errlevels.cmd
:
@ECHO ON >NUL
@SETLOCAL enableextensions enabledelayedexpansion
(call )
@echo ^(call ^) command clears errorlevel %errorlevel%
abcd /G>NUL 2>&1
@echo abcd /G: "'abcd' not recognized" errorlevel %errorlevel%
abcd /G>NUL 2>&1 && echo YES !errorlevel! || echo NO !errorlevel!
@echo abcd /G: ^|^| changed errorlevel %errorlevel%
find /G >NUL 2>&1 && echo YES !errorlevel! || echo NO !errorlevel!
@echo find /G: ^|^| unchanged errorlevel %errorlevel%
call t.cmd 333 && echo YES !errorlevel! || echo NO !errorlevel!
type t.cmd
t.cmd 222 && echo YES !errorlevel! || echo NO !errorlevel!
输出(来自errlevels.cmd
):
==>errlevels.cmd
==>(call )
(call ) command clears errorlevel 0
==>abcd /G 1>NUL 2>&1
abcd /G: "'abcd' not recognized" errorlevel 9009
==>abcd /G 1>NUL 2>&1 && echo YES !errorlevel! || echo NO !errorlevel!
NO 1
abcd /G: || changed errorlevel 1
==>find /G 1>NUL 2>&1 && echo YES !errorlevel! || echo NO !errorlevel!
NO 2
find /G: || unchanged errorlevel 2
==>call t.cmd 333 && echo YES !errorlevel! || echo NO !errorlevel!
NO 333
==>type t.cmd
@exit /B %~1
==>t.cmd 222 && echo YES !errorlevel! || echo NO !errorlevel!
YES 222
==>
注意
||
显示错误级别 1,尽管'abcd' not recognized
错误应该是9009
而||
为FIND: Invalid switch
错误保持错误级别 2 不变。||
分支在call t.cmd 333
中计算&&
分支在t.cmd 222
中计算。
在 (调用)
上参见 DBenham's answer :
If you want to force the
errorlevel
to0
, then you can use this totally non-intuitive, but very effective syntax:(call )
. The space aftercall
is critical.If you want to set the
errorlevel
to1
, you can use(call)
. It is critical that there not be any space aftercall
.
关于windows - 命令脚本退出代码未被同一行 && 或 || 看到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31173772/