windows - 为什么 cmd 在我使用 && 时运行我的第二个命令,即使第一个命令失败了?

标签 windows cmd

我正在试验 Rust。我想编译一个程序,只有编译成功了,才运行。所以我正在尝试:

rustc hello.rs && hello

但 hello.exe 始终运行,即使编译失败也是如此。

如果我尝试

rustc hello.rs
echo Exit Code is %errorlevel% 

我得到“退出代码是 101”。

据我了解,cmd 中唯一的真值是 0,而 101 显然不是,而且 && 是延迟求值的,那么为什么它会运行 hello


rustc.bat 看起来像这样:

@echo off
SET DIR=%~dp0%
cmd /c "%DIR%..\lib\rust.0.11.20140519\bin\rustc.exe %*"
exit /b %ERRORLEVEL%

最佳答案

很好奇这个。把 CALL 放在前面,一切都应该没问题。

call rustc hello.rs && hello

我不完全理解这个机制。我知道 &&|| 不直接读取动态 %errorlevel% 值,而是在某个较低的级别运行。它们根据最近执行的命令的结果有条件地触发,而不考虑当前的 %errorlevel% 值。 || 甚至可以针对未设置 %errorlevel% 的故障触发!参见 File redirection in Windows and %errorlevel%batch: Exit code for "rd" is 0 on error as well例如。

您的 rustc 是一个批处理文件,行为会根据是否使用 CALL 而改变。如果没有 CALL,&&|| 运算符仅响应命令是否运行 - 它们忽略脚本的退出代码。使用 CALL,除了在脚本运行失败(可能脚本不存在)时做出响应外,它们还可以正确响应脚本的退出代码。

换句话说,批处理脚本仅通知 &&|| 运算符(operator)有关通过 CALL 启动的退出代码。

更新

仔细阅读 foxidrive(现已删除)的回答后,我意识到情况更加复杂。

如果使用 CALL,那么一切都会按预期工作 - &&|| 响应脚本返回的 ERRORLEVEL。 ERRORLEVEL 可能在脚本的早期设置为 1,只要后续脚本命令没有清除错误,返回的 1 的 ERRORLEVEL 将被正确地报告给 &&||.

如果不使用 CALL,则 &&|| 响应脚本中最后执行 命令的错误代码。脚本中的早期命令可能会将 ERRORLEVEL 设置为 1。但如果最后一个命令是正确执行的 ECHO 语句,则 &&|| 响应成功ECHO 命令而不是脚本返回的 1 的 ERRORLEVEL。

真正的 killer 是 EXIT/B 1 not 将 ERRORLEVEL 报告给 &&|| 除非脚本是通过 CALL 调用的。条件运算符检测到EXIT命令执行成功,忽略返回的ERRORLEVEL!

如果脚本最后执行的命令是:

cmd /c exit %errorlevel%

这将正确地将返回的 ERRORLEVEL 报告给 &&||,无论脚本是否被 CALL 调用。

这里有一些测试脚本可以证明我的意思。

test1.bat

@echo off
:: This gives the correct result regardless if CALL is used or not
:: First clear the ERRORLEVEL
(call )
:: Now set ERRORLEVEL to 1
(call)

test2.bat

@echo off
:: This only gives the correct result if CALL is used
:: First clear the ERRORLEVEL
(call )
:: Now set ERRORLEVEL to 1
(call)
rem This command interferes with && or || seeing the returned errorlevel if no CALL

test3.bat

@echo off
:: This only gives the correct result if CALL is used
:: First clear the ERRORLEVEL
(call )
:: Now set ERRORLEVEL to 1
(call)
rem Ending with EXIT /B does not help
exit /b %errorlevel%

test4.bat

@echo off
:: This gives the correct result regardless if CALL is used or not
:: First clear the ERRORLEVEL
(call )
:: Now set ERRORLEVEL to 1
(call)
rem The command below solves the problem if it is the last command in script
cmd /c exit %errorlevel%

现在使用和不使用 CALL 进行测试:

>cmd /v:on
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

>test1&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Failure with errorlevel=1

>test2&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Success, yet errorlevel=1

>test3&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Success, yet errorlevel=1

>test4&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Failure with errorlevel=1

>call test1&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Failure with errorlevel=1

>call test2&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Failure with errorlevel=1

>call test3&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Failure with errorlevel=1

>call test4&&echo Success, yet errorlevel=!errorlevel!||echo Failure with errorlevel=!errorlevel!
Failure with errorlevel=1

>

关于windows - 为什么 cmd 在我使用 && 时运行我的第二个命令,即使第一个命令失败了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24583984/

相关文章:

php shell_exec 返回空值

python - 为什么Python中的cmd.cmdloop不会随着cmd.onecmd而停止?

windows - 在 Windows 8 中从 Metro 应用程序触发关机/重启的最佳方式

python - 在Windows 10 cmd中切换不同的Python版本

c# - Process.Start() 什么都不做

windows - 从 CMD 运行 Microsoft TraceView

windows - 权限被拒绝尝试设置全局git配置

java - SFTP使用java从Windows服务器检索文件到Linux服务器

windows - 寻找可以扫描 windows api 兼容性问题的工具

windows - 通过命令行比较文件夹