僅當另一個命令失敗(保留原始輸入)時,如何通過管道傳輸到命令?
我希望這不是重複的,但我做了一些盡職調查,試圖找到並回答。我想將原始輸出通過管道傳遞給第二個命令,前提是第一個命令失敗。
例如
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
第二種形式在 && || 中可能有問題 形式。為了完整起見,我將其包括在此處。
最終,您將不得不決定做什麼
command1
和command2
需要做什麼。我們現在可以將它們組合在一起:
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 的方法。我喜歡保持簡單易懂,因為我不在程式商店,我不知道誰必須維護我的程式碼。