Pipe
鍊式命令的退出狀態
我想在變數中執行一個可能無效的命令
cmd
。我不能讓它失敗並檢索退出狀態。我可以嘗試做的是將它傳送到:
,然後我將獲得成功的退出狀態。$ $cmd | : $ echo $? 0
現在,我想知道
cmd
不執行它的退出狀態。在 Bash 中,我可以使用PIPESTATUS
. 但我正在使用破折號。我試圖執行
bash -c "$cmd | : ; rc=$(echo ${PIPESTATUS[@]} | head -c1)"
,但我得到一個“Bad substituion error”。我的問題是:
- 如何實現我在破折號中返回第一個命令的退出狀態的目標?
- 我正在做什麼會在破折號中產生錯誤?
如果您有完整的 shell 語法可用,那麼您可以使用
if
,這不會顯示為 shell 失敗:if (eval "$cmd"); then : # do nothing, it worked else printf 'Command %s failed with code %d\n' "$cmd" $? fi
請注意,您不能使用更明顯的
if ! eval…
語法,因為否定將隱藏退出程式碼。那裡有“什麼都不做”位,因為 shell 語法需要一個帶有命令的 then 塊;您不能省略它或將其留空。重要的是
if
,即使評估的命令失敗,shell 也不會失敗。括號是在子shell中執行命令;這可以防止命令設置影響腳本的變數或執行類似
exit 1
完全終止腳本的操作。最後,請注意我是如何使用
eval
而不是 unquoted 的$cmd
。那是因為未引用的命令以您可能不期望的方式進行分詞。如果您有cmd='rm -Rf "foo * baz"'
,那麼當您執行時$cmd
,您實際執行的是rm -Rf \"foo * baz\"
-它將擴展*
到目錄中的所有文件,刪除所有內容(除了兩個文件"foo
和baz"
)。這是全域擴展之前的三個參數rm
,而不是您期望的參數。eval
將應用正常的 shell 命令解析,我認為會導致更少的驚喜。如果這是在您的腳本中建構的命令而不是例如從文本文件中讀取的行,則還有其他方法(例如使用數組)更安全。