Bash

僅當另一個命令失敗(保留原始輸入)時,如何通過管道傳輸到命令?

  • June 7, 2021

我希望這不是重複的,但我做了一些盡職調查,試圖找到並回答。我想將原始輸出通過管道傳遞給第二個命令,前提是第一個命令失敗。

例如cat file.txt | command1 || command2,command1 和 command2 都從 STDIN 讀取。

我希望 command1 從 中讀取所有內容cat file.txt,但是,如果失敗。我想將所有輸入執行到 command2 中。

編輯:我現在意識到我的問題有點模棱兩可。我說 command1 和 command2 都從 STDIN 讀取,但我的意思是我希望兩者都從cat file.txt(不一定是特定命令)接收 STDOUT

我想我最初的願望是把這樣的東西放在別名中。5個月後,我不記得這是如何解決的。很可能是通過編寫 bash 腳本。

歡迎來到堆棧交換!這裡有很多很好的資訊。首先感謝您的盡職調查。

我在您的命令中看到的問題是它是“乞求問題”。換句話說,它假設您在開始之前就知道答案。

讓我們仔細看看: cat file.txt

“file.txt”的內容將轉到 STDOUT。

如果“cat”命令產生任何錯誤,它們將對 STDERR 執行。

命令完成後,將設置退出程式碼。0 = 成功;其他任何事情都是錯誤。

這裡的問題是,您不知道是否應該執行command1或者command2直到輸出已經發送。這意味著,它消失了。

將其與此進行比較:

cat file.txt | sort

這實際上是 2 個命令:

1:cat file.txt 1> temp_file

2:sort < temp_file

好的,不是真正的 Unix 命令,這樣做是為了澄清。

1:將 STDOUT 發送到“tempfile”(即 1> 部分)。還將 STDERR 發送到控制台。

2:執行sort命令,從“tempfile”中讀取STDIN。

在兩個命令之間放置管道|可以避免對臨時文件的需要。管道表示:將 STDOUT 從“cat”重定向到“sort”的 STDIN。

您的問題:

您想將 STDOUT 重定向到另一個命令的 STDIN,但您還不知道是哪個命令,因此您無法重定向它。

在我找到一個可能的解決方案之前,讓我給你一些背景知識:

在 Unix 中,有一種方法可以按照你想要的方式執行命令。以機智:

my_command argument1 argument2 && echo "Success" || echo "Failure"

my_command控制台上使用 STDOUT 和 STDERR 執行(並返回其退出狀態)後,執行其中一個或另一個回顯。

&&表示“如果最後一個命令成功

||則執行此操作”表示“如果最後一個命令失敗則執行此操作”

您與原始命令非常接近。你有:

cat file.txt | command1 || command2

讓我們把它改成這樣:

cat file.txt && command1 || command2

除了輸出之外,你得到了你想要的一切。

問題1:

如果cat file.txt有效,那麼應該command1閱讀STDOUT並忽略STDERR嗎?

同樣,如果它失敗了,那麼應該command2讀取 STDERR 並忽略 STDOUT 嗎?

或者,任何一個命令都應該讀取 STDOUT 和 STDERR 嗎?

為了完整起見,我將回答這兩個問題。

無論哪種方式,您都需要一種方法來儲存輸出以供以後處理。通常是一個 temp_file。

在同一個 temp_file 中擷取 STDOUT 和 STDERR:

cat file.txt > /tmp/temp_file 2>&1

將 STDOUT 擷取到 temp_file#1 並將 STDERR 擷取到 temp_file#2:

cat file.txt > /tmp/out_file 2 >/tmp/err_file

問題 2:

是否允許command1和/或command2允許在命令行上使用文件名?

command1 temp_file

是否允許command1和/或command2允許從文件重定向?

command2 < temp_file

command1和/或command2閱讀標準輸入?

cat temp_file | command1

注意:字數統計命令是一個範例。

wc temp_file

cat temp_file | wc

wc < temp_file

第二種形式在 && || 中可能有問題 形式。為了完整起見,我將其包括在此處。

最終,您將不得不決定做什麼command1command2需要做什麼。

我們現在可以將它們組合在一起:

cat file.txt > /tmp/out_file 2>/tmp/err_file && command1 < /tmp/out_file || command2 < /tmp/err_file

然後刪除臨時文件:

rm /tmp/out_file /tmp/err_file

這應該會給你你想要的。

我敢肯定,這裡的其他大師可以想出一種不使用 temp_file 的方法。我喜歡保持簡單易懂,因為我不在程式商店,我不知道誰必須維護我的程式碼。

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