標準出力を複数のコマンドに送信するには?

標準出力を複数のコマンドに送信するには?

入力をフィルタリングするか、それに応じて動作し、それを出力に渡すコマンドがあります。一般的にそのような場合だと思いますstdout。しかし、入力を受け入れ、stdin何も実行し、何も出力しないコマンドもあります。

私はOS Xに最も慣れているので、すぐに思い浮かぶ2つのことは次のpbcopyとおりですpbpaste。 - システムクリップボードにアクセスする方法は次のとおりです。

とにかく、stdoutを取得して出力を2つのファイルにエクスポートしたい場合は、stdoutこのコマンドを使用できることを知っていますtee。私はそれについて何かを知っていますが、xargsそれが私が探しているものではないと思います。

stdout2つ以上のコマンドを切り替えるために分割する方法を知りたいです。たとえば、

cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors

おそらくそれより良い例があるでしょう。しかし、「ミュート」を避けながら、中継しないコマンドにstdoutを送信する方法を知りたいです。ファイルとその一部stdoutを送信する方法を尋ねるものではありません。クリップボードにコピー - 特定のコマンドはそれほど重要ではありません。catgrep

また、ファイルに送信する方法を尋ねるものではありませんstdout。 「重複」の質問かもしれません(申し訳ありません)。しかし、検索をやってみると、stdoutとファイルを分割する方法を尋ねる同様の質問だけが見つかりました。 - 回答 この質問にはtee、私はそれが私には効果がないと思います。

最後に、「パイプラインチェーンの最後のエントリとしてpbcopyを作成するのはどうですか?」と尋ねることができます。私の答えは1)これを使いたいのですが、コンソールで出力を見続けるにはどうすればよいですか? 2)入力を処理した後に出力されない2つのコマンドを使用したい場合はstdoutどうすればよいですか?

teeああ、もう1つ - 名前付きパイプ()を使用できることを知っていますが、事前mkfifo設定を必要とせずにこれをインラインで簡潔に実行する方法があることを望みました。 :)

答え1

代替項目を使用teeして処理できます。

cat file.txt | tee >(pbcopy) | grep errors

これにより、すべての出力がに送信され、cat file.txtコンソールからのみpbcopy結果を取得できます。grep

teeこのセクションには複数のプロセスを配置できます。

cat file.txt | tee >(pbcopy) >(do_stuff) >(do_more_stuff) | grep errors

答え2

に複数のファイル名を指定することができtee、また標準出力をコマンドにパイプすることもできます。出力を複数のコマンドにディスパッチするには、複数のパイプを作成し、各パイプを出力として指定する必要がありますtee。これを行う方法はいくつかあります。

プロセスの置き換え

シェルがksh93、bash、またはzshの場合は、プロセス置換を使用できます。これは、ファイル名を期待するコマンドにパイプを渡す方法です。シェルはパイプを生成し、/dev/fd/3コマンドのようにファイル名を渡します。番号はファイル記述子パイプが接続されています。一部のUNIXバリアントではサポートされていません/dev/fd。代わりに、名前付きパイプが使用されます(下記参照)。

tee >(command1) >(command2) | command3

ファイル記述子

すべてのPOSIXシェルで複数のものを使用できます。ファイル記述子明らかに。/dev/fd出力の1つを除くすべての項目をtee名前で指定する必要があるため、これにはサポートされているunixバリアントが必要です。

{ { { tee /dev/fd/3 /dev/fd/4 | command1 >&9;
    } 3>&1 | command2 >&9;
  } 4>&1 | command3 >&9;
} 9>&1

名前付きパイプ

最も基本的で移植可能な方法は、以下を使用することです。名前付きパイプ。欠点は、書き込み可能なディレクトリを見つけてパイプを作成してクリーンアップする必要があることです。

tmp_dir=$(mktemp -d)
mkfifo "$tmp_dir/f1" "$tmp_dir/f2"
command1 <"$tmp_dir/f1" & pid1=$!
command2 <"$tmp_dir/f2" & pid2=$!
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
rm -rf "$tmp_dir"
wait $pid1 $pid2

答え3

プロセスの置き換えで遊んでください。

mycommand_exec |tee >(grep ook > ook.txt) >(grep eek > eek.txt)

grepmycommand_exec出力はプロセス固有の入力と同じ2つのバイナリです。

答え4

しかもpee~からその他のユーティリティパック。これは以下のために設計されています:

pee 'command1' 'command2' 'cat -'

関連情報