windows - 命令脚本退出代码未被同一行 && 或 || 看到?

标签 windows batch-file cmd

考虑一个名为 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

==>

资源

编辑启发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 to 0, then you can use this totally non-intuitive, but very effective syntax: (call ). The space after call is critical.

If you want to set the errorlevel to 1, you can use (call). It is critical that there not be any space after call.

关于windows - 命令脚本退出代码未被同一行 && 或 || 看到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31173772/

相关文章:

batch-file - 如果 Windows "Admin"用户名已更改,则批处理文件转到下一个 xcopy 命令

batch-file - CMD 文件 - 延迟变量扩展

c# - 防止Winform最大化?

windows - 批量请求用户输入(/P)时换行?

windows - 如何为 SQL*Plus (Windows) 实例设置窗口标题?

regex - Windows 中的 Perl 单行代码

windows - cmd.exe/k (echo %1 & echo %~n1) 放入注册表命令项时未按预期输出

windows - ffmpeg 在 forfiles 循环中调用时覆盖输入文件

batch-file - 更改暂停消息

java - 如何在windows中使用cmd启动程序