我遇到了ss64.com,它为如何编写Windows命令解释器将运行的批处理脚本提供了很好的帮助.
但是,我一直无法找到批处理脚本的语法,扩展或不扩展的方法,以及如何逃避事情的良好解释.
以下是我无法解决的示例问题:
foreach $i (@ARGV) { print '*' . $i ; }),编译它并以这种方式调用它:
my_script.exe "a ""b"" c"?输出是 *a "b*cmy_script.exe """a b c"""?输出它*"a*b*c"echo命令如何工作?在那个命令中扩展了什么?for [...] %%I在文件脚本中使用,但for [...] %I在交互式会话中?%PROCESSOR_ARCHITECTURE%字面回声?我发现echo.exe %""PROCESSOR_ARCHITECTURE%有效,有没有更好的解决方案?%配对?例:
set b=a,echo %a %b% c%?%a a c%set a =b,echo %a %b% c%?bb c%在Windows批处理脚本中处理错误的常用方法是使用
if errorlevel 1 ...或等if %errorlevel% neq 0 ....通常,人们希望错误处理代码保留ERRORLEVEL.
我相信所有外部命令总是会导致ERRORLEVEL被设置为某个值,因此错误处理代码必须在执行外部命令之前在环境变量中保留ERRORLEVEL.
但内部命令怎么样?问题是,一些内部命令在成功时将ERRORLEVEL清除为0,而有些则没有.而且我找不到任何指定哪些命令做什么的文档.
所以问题是,哪些内部命令成功后将ERRORLEVEL清除为0?这不是关于返回的ERRORLEVEL代码的一般问题,而是严格关于成功结果的问题.
有些帖子如何将ERRORLEVEL重置为零的最简单方法是什么?和Windows批处理文件:.bat vs .cmd?给出部分答案.但我从未见过全面的清单.
注意: 多年来我一直很好奇.所以我最终决定进行一系列实验并得出一个明确的答案.我发布此问答来分享我发现的内容.
ERRORLEVEL是大多数cmd.exe命令在根据一系列条件结束更改时返回的值,因此知道命令返回的值是有助于编写更好的批处理文件的有用信息.所有外部.exe程序在结束时都会更改ERRORLEVEL(这是ExitProcess和TerminateProcess Win-32 API函数的固有机制),并且通常记录这些值,但内部 cmd.exe命令返回的值在其他地方没有完整记录.
此问题中出现具有部分ERRORLEVEL值的表,但仅适用于成功时设置ERRORLEVEL = 0的内部命令.我建议OP这样的问题修改它,以便也包括"不成功的命令"返回的值,但他拒绝并邀请我发布我自己的问题/答案,所以在这里!必须注意的是大于零的不同ERRORLEVEL并没有必然意味着该命令失败!有些命令以无错误结束并返回大于零的值以指示不同的"退出状态",包括内部命令(如SET /P).
为了更好地使用Batch .bat文件中的内置cmd.exe命令,我们需要知道它们返回的ERRORLEVEL值以及此管理中涉及的机制.所以问题是,哪个内部cmd.exe命令将ERRORLEVEL设置为任何值(包括零)?
在重定向失败时(由于文件不存在或文件访问不足),ErrorLevel似乎没有设置该值(在以下示例中,文件test.tmp是写保护的,文件test.nil不存在):
>>> (call ) & rem // (reset `ErrorLevel`)
>>> > "test.tmp" echo Text
Access is denied.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
>>> (call ) & rem // (reset `ErrorLevel`)
>>> < "test.nil" set /P DUMMY=""
The system cannot find the file specified.
>>> echo ErrorLevel=%ErrorLevel%
ErrorLevel=0
Run Code Online (Sandbox Code Playgroud)
但是,只要失败的重定向后面跟着||查询退出代码的条件连接运算符,ErrorLevel就会1意外地设置为:
>>> (call ) & rem // (reset `ErrorLevel`)
>>> (> "test.tmp" echo Text) || echo Fail
Access is denied.
Fail
>>> …Run Code Online (Sandbox Code Playgroud) 我面临一个奇怪的情况,我写的批处理文件报告错误的退出状态.这是一个重现问题的最小样本:
bug.cmdecho before
if "" == "" (
echo first if
exit /b 1
if "" == "" (
echo second if
)
)
echo after
Run Code Online (Sandbox Code Playgroud)
如果我运行这个脚本(使用Python但问题实际上也是以其他方式启动时),这就是我得到的:
python -c "from subprocess import Popen as po; print 'exit status: %d' % po(['bug.cmd']).wait()"
echo before
before
if "" == "" (
echo first if
exit /b 1
if "" == "" (echo second if )
)
first if
exit status: 0
Run Code Online (Sandbox Code Playgroud)
注意尽管应该如何exit status报告.0exit /b 11
现在奇怪的是,如果我删除了内部 …
我已经编写了一个.bat文件来首先运行一个程序,如果它正确完成,我运行另一个程序并检查它的返回值。
first-program.exe
IF "%ERRORLEVEL%"=="0" (
second-program.exe
IF "%ERRORLEVEL%"=="0" (
ECHO OK
) ELSE (
ECHO NOK
)
)
Run Code Online (Sandbox Code Playgroud)
但是,第二个%ERRORLEVEL%始终等于第一个,它不会设置为 的返回值second-program.exe。