为什么没有使用流水线命令启用delayedexpansion?

时间:2012-11-12 15:50:59

标签: windows batch-file

我正在尝试使用Windows批处理文件来运行命令,将其输出传递给另一个命令,并捕获第一个命令的退出状态。但显然,我不能这样做,虽然我会批准Windows批处理文件如此神秘,以至于我可能错过了一种技术。 如何捕获命令的退出状态并管道输出?

这是经典的do_a_thing | tee logfile.txt用法,但我希望能够检查do_a_thing是否成功。经过大量的鬼混,谷歌搜索和阅读StackOverflow后,我想出了以下内容:

setlocal enabledelayedexpansion
set rc=-1
( false & set rc=!errorlevel! & echo rc=!rc! ) | tee logfile.txt
echo %rc%

我曾希望能产生:

C:\>test.bat 
C:\>setlocal enabledelayedexpansion 
C:\>set rc=-1 
C:\>(false & set rc=!errorlevel!   & echo rc=!rc!  ) | tee logfile.txt
rc=1 
C:\>echo 1
1

但是,唉,它没有:

C:\>test.bat
C:\>setlocal enabledelayedexpansion
C:\>set rc=-1
C:\>(false & set rc=!errorlevel! & echo rc=!rc! ) | tee logfile.txt
rc=!rc!
C:\>echo -1
-1

删除“| tee logfile.txt”会产生!rc!的预期值,但当然,它不会让我捕获日志文件。

C:\>test.bat
C:\>setlocal enabledelayedexpansion
C:\>set rc=-1
C:\>(false & set rc=!errorlevel! & echo rc=!rc! )
rc=1
C:\>echo 1
1

1 个答案:

答案 0 :(得分:2)

您尝试执行的操作无效,因为管道的每一侧都在命令行上下文中在其自己的命令shell中执行,默认情况下延迟关闭。有关详细信息,请参阅Why does delayed expansion fail when inside a piped block of code?。接受的答案解释了所有内容,其他答案有助于为接受的答案提供背景信息。

最简单的解决方案是将错误代码写入临时文件,然后在命令完成后将文件读入变量。

( false & call echo %%^^errorlevel%%>returnCode.txt ) | tee logfile.txt
set "rc="
<returnCode.txt set /p "rc="
del returnCode.txt
echo rc=%rc%

CALL语句提供了在命令运行后发生的另一级解析。诀窍是延迟扩展OF%errorlevel%,直到你正在测试的命令运行。在命令上下文中,您只需使用CALL ECHO %^ERRORLEVEL%即可。但是命令行在到达命令上下文之前还必须通过批处理上下文解析,因此百分比必须转义为%%且插入符号为^^