他のコマンドが失敗した場合にのみ1つのコマンド(元の入力を保持)にパイプする方法は?

他のコマンドが失敗した場合にのみ1つのコマンド(元の入力を保持)にパイプする方法は?

重複ではないことを願っていますが、見つけて答えようと実写をしました。最初のコマンドが失敗した場合にのみ、生の出力を2番目のコマンドにパイプしたいと思います。

例えば、cat file.txt | command1 || command2command1 と command2 の両方が STDIN から読み取られます。

私はcommand1がすべてを読みたいのcat file.txtですが、それが失敗した場合。 command2ですべての入力を実行したいです。

編集:今私の質問が少し曖昧であることに気づきました。私はcommand1とcommand2が両方ともSTDINから読み取られたと言いましたが、私が意味するのは両方ともcat file.txtSTDOUTを受信したいということです(必ずしも特定のコマンドである必要はありません)。

私の元の希望は、このようなものをエイリアスに入れることだったようです。 5ヶ月が過ぎた今、この問題がどのように解決されたのか覚えていません。 bashスクリプトを書くのが最も可能性が高いです。

答え1

スタック交換へようこそ!ここには良い情報がたくさんあります。まず、ご注意ください。

あなたの注文で私が見た問題は、「質問を引き起こす」ことです。つまり、始める前に答えを知っているとします。

もう少し詳しく見てみましょう。 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を読み込みます。 2つのコマンドの間に
パイプを置くと、|一時ファイルは必要ありません。パイプの意味は、STDOUTを「cat」から「sort」のSTDINにリダイレクトすることです。

問題:
STDOUTを他のコマンドのSTDINにリダイレクトしたいのですが、まだどのコマンドがあるのか​​わからないため、リダイレクトできません。

考えられる解決策を議論する前に、いくつかの背景知識をお知らせします。
Unixには、必要な方法でコマンドを実行する方法があります。気をつけて:
my_command argument1 argument2 && echo "Success" || echo "Failure"

my_commandコンソールでSTDOUTとSTDERRを使用して実行し(そして終了ステータスを返した後)、一方または他のechoを実行します。
&&「最後のコマンドが成功した場合はこれを実行してください」とは、
||「最後のコマンドが失敗した場合はこれを実行してください」を意味します

。元のコマンドと非常に似ています。
cat file.txt | command1 || command2
次のように変更します。これは、
cat file.txt && command1 || command2
出力を除いて必要なものすべてを提供します。

Q1:有効な
場合はSTDOUTを読み、STDERRを無視する必要がありますか?同様に、失敗した場合はSTDERRを読み取り、STDOUTを無視する必要がありますか?それとも、両方のコマンドのいずれかがSTDOUTとSTDERRの両方を読み取る必要がありますか?完全性を期すために、両方の質問に答えます。どちらにしても、後で処理するために出力を保存する方法が必要です。通常は一時ファイルです。同じtemp_fileからSTDOUTとSTDERRをキャプチャします。cat file.txtcommand1
command2






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:コマンドラインでファイル名を使用できますか
command1command2
command1 temp_file

ファイルからのリダイレクトを許可してcommand1いますか?command2
command2 < temp_file

STDINを実行command1および/またはcommand2読みますか?
cat temp_file | command1

注:単語数コマンドは例です。
wc temp_file
cat temp_file | wc
wc < temp_file
2番目の形式は、&& ||に問題のある形式がある可能性があります。完全性のためにここに入れます。

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を使用せずに方法を見つけることができると確信しています。私はプログラミング作業室にいなくても、誰が私のコードを管理するのか分からないので、仕事を簡単で理解しやすくするのが好きです。

答え2

これを行う唯一の方法は、出力をcommand1ファイルに書き込んで読み取ることですcommand2

set -o errexit
command1 < file.txt > 1.out
command2 < 1.out

または

if command1 < file.txt > 1.out
then
    command2 < 1.out
fi

もちろん、この時点ではパイプラインの非同期処理の利点は消えます。

答え3

簡単な方法は、ファイルストリームをfile

command1 < file || command2 < file

または

if command1 < file; then
    echo 'first command was successful'
else 
    command2 < file
fi

または出力したい内容に応じて同様の構文。

同時に、2つのコマンドで同じファイルストリームを使用するには、同様の方法またはtee類似の方法を使用する必要があります。これは、返す前に処理を開始する必要があるcommand2command1、またはある種のバッファリングを使用する必要があることを意味します。 、おそらくいくつかの信号があるかもしれません。優れた拡張可能なバッファはディスク上のファイルです。

関連情報