我正在试用Rust。 我想编译一个程序,只有成功,运行它。 所以我试着:
rustc hello.rs && hello
但hello.exe总是运行,即使编译失败。
如果我尝试
rustc hello.rs echo Exit Code is %errorlevel%
我得到“退出代码是101”。
据我了解,唯一的truthy值是0 cmd,其中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%
失败! 请参阅Windows中的文件重定向和%errorlevel%和批处理:错误中的“rd”的退出代码也是例子。
您的rustc
是一个批处理文件,并且行为根据是否使用CALL而改变。 没有CALL, &&
和||
操作员只响应命令是否运行 – 他们忽略脚本的退出代码。 通过CALL,他们可以正确响应脚本的退出代码,除了响应脚本运行失败(也许脚本不存在)之外。
换句话说,批处理脚本只能通知&&
和||
有关退出代码的操作员是否通过CALL启动。
UPDATE
阅读foxidrive的(现在删除)答案更仔细,我意识到情况更复杂。
如果使用CALL,则一切按预期工作 – &&
和||
响应脚本返回的ERRORLEVEL。 在脚本中,ERRORLEVEL可以设置为1,只要没有后续脚本命令清除错误,返回的ERRORLEVEL为1就会正确地报告给&&
和||
。
如果不使用CALL,那么&&
和||
响应脚本中最后执行的命令的错误代码。 脚本中的早期命令可能会将ERRORLEVEL设置为1.但是,如果最后一个命令是正确执行的ECHO语句,那么&&
和||
响应ECHO命令的成功,而不是脚本返回的ERRORLEVEL 1。
真正的杀手是EXIT /B 1
不会将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 >
快速演示来证明这一点:
@ECHO OFF SETLOCAL CALL q24983584s 0&&ECHO "part one" ECHO done one CALL q24983584s 101&&ECHO "part two" ECHO done two GOTO :EOF
q24983584s.bat
在哪里
@ECHO OFF SETLOCAL EXIT /b %1 GOTO :EOF
按预期工作…