nmake | tee output.txt
你可能认为可以做以下操作,但它不起作用。
(nmake & call set myError=%%errorlevel%%) | tee output.txt
问题在于Windows管道的工作机制。每个管道端在它自己的CMD shell中执行。所以你在那里设置的任何环境变量都会在命令结束后消失。此外,由于额外的解析级别和CMD shell具有命令行上下文而不是批处理上下文,%errorlevel%的延迟展开更加复杂。
你可以采取以下措施:
(nmake & call echo %%^^errorlevel%% ^>myError.txt) | tee output.txt
for /f %%A in (myError.txt) do echo nmake returned %%A
del myError.txt
或者你可以将errorlevel嵌入到你的output.txt中:
(nmake & call echo nmakeReturnCode: %%^^errorlevel%%) | tee output.txt
for /f "tokens=2" %%A in ('findstr /b "nmakeReturnCode:" output.txt') do echo nmake returned %%A
以上两种解决方案都假设您正在批处理脚本中运行命令。如果您要从命令行执行命令,则两个解决方案都需要使用 %^^errorlevel%
而不是 %%^^errorlevel%%
。
但是,考虑到nmake不需要用户输入,并且通常速度很快,因此实时监控可能不是问题,那么最简单的解决方案似乎是
nmake >output.txt
set myError=%errorlevel%
type output.txt
echo nmake returned %myError%
注意 - 在使用Windows管道时存在许多微妙的复杂性。一个很好的参考是为什么在代码块内部使用延迟扩展失败?。我建议阅读问题和所有答案。被选中的答案拥有最佳信息,但其他答案可以帮助提供背景。
编辑 2015-06-02
我最近发现你可以使用DOSKEY宏来干净地存储和检索一个(或两个)管道的ERRORLEVEL,而不必诉诸于临时文件。我的想法来自DosTips用户Ed Dyreen在http://www.dostips.com/forum/viewtopic.php?p=41409#p41409上。DOSKEY宏无法通过批处理执行,但定义会在ENDLOCAL 和 CMD /C exit之后保留!
以下是您在该情况下如何使用它:
(nmake & call doskey /exename=err err=%%^^errorlevel%%) | tee output.txt
for /f "tokens=2 delims==" %%A in ('doskey /m:err') do echo nmake returned %%A
如果需要的话,你可以在最后添加一个命令来清除 err "宏"的定义,以便在获取值后进行清理。doskey /exename=err err=
有一种名为"mtee"的“tee”版本(可在https://ritchielawrence.github.io/mtee/上找到),它可选择性地采用管道进程的退出代码。使用它,您可以编写以下代码:
nmake | mtee /E output.txt
受 @dbenham 回答的启发,我制作了以下版本:
(%cmd% & call echo EXIT /B %^^ERRORLEVEL% >%ret_file%)
| tee %log_file% & %ret_file%>NUL
EXIT /B <some_error_value>
call set
、call echo
等等的意思是什么?我之前从未见过这种语法。 - alecovecho !var!
类似于call echo %%var%%
。通常更喜欢使用延迟扩展,但有时需要使用CALL技巧。 - dbenham(echo 正在退出... & cmd /c exit /b 1234 & call echo %^^errorlevel% > myerror.txt) | tee file.txt
,因为在批处理文件中只有百分号会加倍以进行转义。 - Brent Rittenhouse