Bash

使用程序替換時如何正確擷取退出程式碼/處理錯誤?

  • January 17, 2017

我有一個腳本,它使用以下方法將文件名解析為數組,該方法取自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避免添加額外的\newline——這很重要,因為即使是read定期執行的——你沒有在 NUL 上劃定界限的\0——在它剛剛讀入的數據沒有結束的情況下也會返回 0 以外的值一條\n線。因此,如果您的最後一行沒有以\newline 結尾,那麼您讀取的變數中的最後一個值將是您的返回值。

執行上面的命令,然後:

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=...部分並不是絕對必要的——它只是用來展示這個概念。

引用自:https://unix.stackexchange.com/questions/128560