在 Windows 批處理檔案中,我需要處理命令的輸出
for /f %%a in ('aCommand') do (
...
)
但是,如果aCommand失敗,我想用exit /b 1. 我試過了
for /f %%a in ('aCommand') do (
...
) || exit /b 1
但這沒有用;無論如何,腳本的執行都會繼續進行。有什么線索嗎?
uj5u.com熱心網友回復:
至少有三種可能的解決方案。
第一個用于處理由執行命令輸出并由FOR回圈處理的多行。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "OutputProcessed="
for /F %%I in ('aCommand 2^>nul') do (
set "OutputProcessed=1"
rem Other commands processing the string(s) assigned to the loop variable(s).
)
if not defined OutputProcessed exit /B 1
set "OutputProcessed="
rem Other commands to run by the batch file.
endlocal
首先確保環境變數OutputProcessed在運行之前不是偶然定義的,for /F這會導致在后臺啟動cmd.exe選項和附加引數/c之間的命令列。'
環境變數是用一個字串值定義的,如果在FOROutputProcessed回圈內處理任何捕獲的輸出行,這并不重要,這意味著在后臺執行的命令列輸出由FOR回圈內的命令處理的內容。cmd.exe
FOR回圈下方的 IF 條件檢查是否未定義環境變數,這意味著從執行命令中沒有處理任何有用的內容。在這種情況下,批處理檔案處理退出,退出代碼指示父行程的錯誤情況。OutputProcessed1
如果將來自已執行命令的輸出的資料分配給至少一個環境變數,則此解決方案是最好的,因為此環境變數可用于檢查命令執行是否成功,而不是使用示例中使用的單獨環境變數。
第二種解決方案與第一種非常相似,只是環境變數處理被倒置了。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NoOutputProcessed=1"
for /F %%I in ('aCommand 2^>nul') do (
set "NoOutputProcessed="
rem Other commands processing the string(s) assigned to the loop variable(s).
)
if defined NoOutputProcessed exit /B 1
rem Other commands to run by the batch file.
endlocal
NoOutputProcessed該解決方案首先用一個無關緊要的值顯式定義環境變數,并在從已執行命令的輸出處理的任何行上取消定義環境變數。如果在執行FOR回圈NoOutputProcessed后仍然定義了環境變數并將錯誤退出代碼回傳給父行程,則退出批處理檔案處理。1
此解決方案適用于使用FOR回圈內的命令進一步處理已執行命令的多行輸出而不將資料分配給一個或多個環境變數的用例。
第三種解決方案最好在執行命令時執行,其中只有一個輸出行包含感興趣的資料,這些資料由批處理檔案進一步處理。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F %%I in ('aCommand 2^>nul') do (
rem Other commands processing the string(s) assigned to the loop variable(s).
goto HaveData
)
exit /B 1
:HaveData
rem Other commands to run by the batch file.
endlocal
在這種情況下,在從后臺命令列程執行的命令的捕獲輸出中獲取感興趣的資料后,使用命令GOTO退出FOR回圈的執行。批處理檔案處理繼續使用標簽下方的行。否則,整個批處理檔案處理將退出,并退出代碼,而不是從執行的命令中獲取感興趣的資料。1
要了解使用的命令及其作業原理,請打開命令提示符視窗,在其中執行以下命令,并仔細閱讀每個命令顯示的所有幫助頁面。
echo /?endlocal /?exit /?for /?goto /?if /?rem /?set /?setlocal /?
閱讀有關使用命令重定向運算子的Microsoft 檔案,了解2>nul. 當 Windows 命令解釋器在執行命令FOR之前在后臺啟動的單獨命令列程中執行嵌入式命令列時,重定向運算子>必須^在FOR命令列上使用脫字符進行轉義,以將其解釋為文字字符。
uj5u.com熱心網友回復:
主要問題是如何定義執行命令的成功或失敗。下面的代碼詳細闡述了三個不同的定義——在STDOUT沒有輸出,在STDERR有一些輸出,退出代碼或ErrorLevel集合:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_CMDL=ver" & rem // (successful command line)
::set "_CMDL=set ^=" & rem // (alternative failing command line)
set "_TMPF=%TEMP%\%~n0_%RANDOM%.log" & rem // (temporary file)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
rem /* In case of an error, the command does not return anything at STDOUT:
rem hence `for /F` has got nothing to capture, in which case it sets the
rem exit code (but not the `ErrorLevel`!) to `1`; this can be detected
rem using the conditional execution operator `||`, given that the entire
rem `for /F` loop is put in between a pair of parentheses: */
(
rem // Remove `2^> nul` to also return a potential error message:
for /F delims^=^ eol^= %%K in ('%_CMDL% 2^> nul') do (
rem // Process an output line here...
echo(%%K
)
) || (
>&2 echo ERROR!& rem exit /B
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
rem /* In case of an error, the command returns something at STDERR:
rem so let us redirect STDOUT to a file for later usage and STDERR to STDOUT
rem to be captured by `for /F`; if the loop iterates STDERR was not empty: */
(
for /F delims^=^ eol^= %%K in ('%_CMDL% 2^>^&1 ^> "%_TMPF%"') do (
>&2 echo ERROR!& del "%_TMPF%" & rem exit /B 1
)
) || (
rem /* Now process the temporary file containing the original STDOUT data;
rem remember that `for /F` would anyway not iterate until the command has
rem finished its execution, hence there is no additional delay: */
for /F usebackq^ delims^=^ eol^= %%K in ("%_TMPF%") do (
rem // Process an output line here...
echo(%%K
)
del "%_TMPF%"
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
rem /* In case of an error, the command sets the exit code or `ErrorLevel`:
rem hence let us suppress a potential error message (unless `2^> nul` is
rem removed), redirect STDOUT to a file for later usage and just output `#`
rem to STDOUT in case the exit code is set (detected by the `||` operator);
rem `for /F` captures the `#` and iterates once in case it is present: */
(
for /F %%K in ('%_CMDL% 2^> nul ^> "%_TMPF%" ^|^| echo #') do (
>&2 echo ERROR!& del "%_TMPF%" & rem exit /B 1
)
) || (
rem // Now process the temporary file containing the original STDOUT data:
for /F usebackq^ delims^=^ eol^= %%K in ("%_TMPF%") do (
rem // Process an output line here...
echo(%%K
)
del "%_TMPF%"
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
endlocal
exit /B
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/485740.html
下一篇:使批處理檔案等待另一個批處理檔案
