コマンドの出力を複数のコマンドにリダイレクトすることは可能ですか?


21

私の知る限り、teeコマンドを使用して、標準出力を画面とその他のファイルに分割できます。

command -option1 -option2 argument | tee file1 file2 file3 

teeを使用してファイルの代わりにコマンドに出力をリダイレクトすることは可能ですか?理論的にはコマンドのチェーンを作成できますか?


3
「出力信号」が意味することを説明し、「コマンドのネットワーク」の作成が意味することを説明します。
ジャニス

Linuxでは、各コマンドには1つの入力と2つの出力があります。それらには、0(入力用)、1(出力用)、2(エラー出力用)のラベルが付いています。「コマンドのネットワーク」と言ったとき、Tコマンドは1というラベルの付いた出力のみを分割することを読んだため、「出力信号」と言ったときに1を考えていました。数学的な観点ですが、私は単にコマンドのツリーを類型的に話すことを考えていたので、いくつかのコマンドは複数の子コマンドの親になることができます。
アブドゥルアルハズレッド

ご説明いただきありがとうございます。Unixでは特定の意味を持ち、この文脈ではこの用語は非常に誤解を招く可能性があるため、信号という単語は使用しないでください。再度、感謝します。
ジャニス

コマンドラインでman -k signalと入力して、UNIXおよびLinuxのこの重要な概念の特別な意味を学習します。man killは、始めるのに適したページです。
ロブ

また、多くの人は、入力または出力の「ストリーム」としてstdin stdoutおよびstderrを参照します。データの小さな川のようなものがあるため、ストリームです。あなたはそれらをまとめて説明するために言葉に取り組むことは正しいのですが、シグナルはただの間違った言葉です。
ロブ

回答:


25

コマンドラインで名前付きパイプ(http://linux.die.net/man/1/mkfifo)を使用teeして、名前付きパイプでコマンドを読み取ることができます。

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2

場合command仕上げは、teeそれぞれに(0バイトの読み出し)EOF信号を送る名前付きパイプ、閉じ/tmp/dataN正常終了であろうがcmdNプロセス。実際の例:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37

バックグラウンドプロセスのため、シェルはプログラム出力の前にプロンプ​​トを返しました。3つのインスタンスはすべてwc正常に終了しました。


1
ではbashの、あなたのことができ、タイピングの安全Aロットを経由して/tmp/data/{0,1,2}。次に、bashでプロセス置換使用してmkfifo完全にスキップすることができます
トビアスキンツラー

2
/ dev / data0を/ tmp / data0に変更したい場合があります。また、シェルにとらわれない方法で質問に答えてくれてありがとう。これは、全員がbashを使用していると想定するよりも役立ちます。
-abonet

15

私が正しく理解していれば、あなたはに相当するものを探していますがtee file1 file2 file3、同じデータを3つのファイルfile1file2およびfile3に書き込むのではなく、同じデータを3つのコマンドcmd1cmd2およびにパイプしたいcmd3、つまり

… | ??? cmd1 cmd2 cmd3

と同等でなければなりません

… | cmd1 &
… | cmd2 &
… | cmd3 &

ただし、実行されるのは1回だけです。

それを行うには2つの方法があります。

Ksh93、bashおよびzshはプロセス置換をサポートします。これは、パイプの一般化であり、コマンドの引数を、書き込み時にデータをコマンドへの入力として渡すファイルにすることができます(コマンドからの出力時にデータを取得する入力バリアントもあります) 。あれは、

echo hello | tee >(cmd1)

プリントhello標準出力へと加えを実行cmd1してhello、入力として。

あなたが入力を複製したいのであれば、たとえば、somecommand両方にそれを渡すcmd1cmd2、あなたが使用することができます

somecommand | tee >(cmd1) | cmd2

シェルがプロセス置換をサポートしていない場合は、代わりに名前付きパイプを使用できます。それがどのように機能するかについては、Arcegeの回答を参照してください。名前付きパイプは、作成して削除し、プロセスを手動で開始および同期する必要があるため、プロセス置換よりも便利ではありません。すべてのシェルがプロセス置換をサポートしているわけではありませんが、完全に移植可能であるという利点があります。また、プロセス置換の対象となるシナリオ以外のシナリオでも使用できます。

内部では、一部のシステムでは、プロセス置換は名前付きパイプを内部的に使用します。ただし、ほとんどのシステムでは、ファイル記述子を表す名前付きファイルに依存しています


5
peeからも参照してくださいmoreutils
ステファンシャゼル

プロセス置換はksh88によって導入されたことに注意してください。
ステファンシャゼル

6

少なくともでは、mkfifoプロセス置換の使用をスキップできます。

command -option1 -option2 argument | tee >(cmd1) >(cmd2) >(cmd3)

またはArcegeの例を採用する

tee >(wc -l) >(wc -w) >(wc -c) < /etc/passwd >/dev/null

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.