Bash
使用程序替換時如何正確擷取退出程式碼/處理錯誤?
我有一個腳本,它使用以下方法將文件名解析為數組,該方法取自SO 上的 Q&A:
unset ARGS ARGID="1" while IFS= read -r -d $'\0' FILE; do ARGS[ARGID++]="$FILE" done < <(find "$@" -type f -name '*.txt' -print0)
這很好用,可以完美地處理所有類型的文件名變體。但是,有時我會將一個不存在的文件傳遞給腳本,例如:
$ findscript.sh existingfolder nonexistingfolder find: `nonexistingfile': No such file or directory ...
在正常情況下,我會讓腳本擷取退出程式碼,
RET=$?
並使用它來決定如何繼續。這似乎不適用於上面的流程替換。在這種情況下,正確的程序是什麼?如何擷取返回碼?是否有其他更合適的方法來確定替代過程中是否出現問題?
您可以通過在其標準輸出上回顯其返回值,輕鬆地從任何子殼程序中獲得返回值。程序替換也是如此:
while IFS= read -r -d $'\0' FILE || ! return=$FILE do ARGS[ARGID++]="$FILE" done < <(find . -type f -print0; printf "$?")
如果我執行它,那麼最後一行 - *(或
\0
視情況而定的分隔部分)*將是find
’ 的返回狀態。read
當它獲得 EOF 時將返回 1 - 所以唯一的時間$return
設置為$FILE
讀入的最後一點資訊。我過去常常
printf
避免添加額外的\n
ewline——這很重要,因為即使是read
定期執行的——你沒有在 NUL 上劃定界限的\0
——在它剛剛讀入的數據沒有結束的情況下也會返回 0 以外的值一條\n
線。因此,如果您的最後一行沒有以\n
ewline 結尾,那麼您讀取的變數中的最後一個值將是您的返回值。執行上面的命令,然後:
echo "$return"
輸出
0
如果我改變流程替換部分……
... done < <(! find . -type f -print0; printf "$?") echo "$return"
輸出
1
一個更簡單的展示:
printf \\n%s list of lines printed to pipe | while read v || ! echo "$v" do :; done
輸出
pipe
事實上,只要您想要的返回是您從程序替換中寫入 stdout 的最後一件事 - 或者您以這種方式讀取的任何子外殼程序 - 那麼
$FILE
它總是會是您想要的返回狀態是通過。所以這|| ! return=...
部分並不是絕對必要的——它只是用來展示這個概念。