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

mpe*_*pen 6 windows cmd

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

rustc hello.rs && hello
Run Code Online (Sandbox Code Playgroud)

但是即使编译失败,hello.exe也会一直运行.

如果我试试

rustc hello.rs
echo Exit Code is %errorlevel% 
Run Code Online (Sandbox Code Playgroud)

我得到"退出代码是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%
Run Code Online (Sandbox Code Playgroud)

dbe*_*ham 9

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

call rustc hello.rs && hello
Run Code Online (Sandbox Code Playgroud)

我不完全理解这个机制.我知道&&并且||%errorlevel%直接读取动态值,而是在较低级别操作.无论当前%errorlevel%值如何,它们都会根据最近执行的命令的结果有条件地触发.该||甚至可以触发该不设置失败%errorlevel%!请参阅Windows中的文件重定向和%errorlevel%批处理:对于示例,出错"rd"的退出代码为0.

rustc是批处理文件,行为会根据是否使用CALL而更改.如果没有呼叫时,&&||运营商只响应命令是否跑或不-他们忽视了脚本的退出代码.使用CALL,它们可以正确响应脚本的退出代码,以及响应脚本是否无法运行(可能脚本不存在).

换句话说,如果通过CALL启动退出代码,批处理脚本只会通知操作员&&||操作员.

UPDATE

在仔细阅读foxidrive(现已删除)答案后,我意识到情况更复杂.

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

如果不使用CALL,然后&&||回应的错误代码上次执行的脚本命令.在剧本的早期命令可以设置ERRORLEVEL为1.但是,如果最后一个命令是执行得当,那么ECHO语句&&||命令echo而不是1脚本返回的ERRORLEVEL的成功作出回应.

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

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

cmd /c exit %errorlevel%
Run Code Online (Sandbox Code Playgroud)

这将返回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)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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%
Run Code Online (Sandbox Code Playgroud)

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%
Run Code Online (Sandbox Code Playgroud)

现在使用和不使用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

>
Run Code Online (Sandbox Code Playgroud)

  • @Mark - 如果脚本未被调用,则“EXIT /B”命令将屏蔽返回代码。仅当脚本执行的最后一个命令是“cmd /c exit %errorlevel%”时,它才有效。也许最简单的方法是在调用脚本时始终使用 CALL。 (2认同)