パイプを分岐する
シェルのパイプ構文(|
)による入出力ストリームはプロセスを直列で接続します。プロセスAの出力を分岐/複製して、プロセスBとプロセスCに並列接続で同じデータを渡すことは、パイプ構文だけを用いてシンプルに実現することはできません。
古くから、シェルで一つの出力を複数プロセスへ分岐させる手段として、FIFO (名前付きパイプ) とtee
コマンドを組み合わせる方法が知られています。W. Richard Stevensの「Advanced Programming in the UNIX® Environment」でも、具体的なコード付きで紹介されています。
mkfifo fifo1
prog3 < fifo1 &
prog1 < infile | tee fifo1 | prog2
# 出典: W. Richard Stevens, Stephen A. Rago. Advanced Programming in the UNIX® Environment, Third Edition
ですが、正直に言って面倒ですよね。スクリプトファイルならともかくコマンドラインでこれをやろうとは思えません。FIFOの削除も意識しなければなりません。
ワンライナーでやる
プロセス置換 (Process Substitution) に対応したシェル限定ですが、プロセス置換を活用することで上記のコードをワンライナーで書くことできます。FIFOの削除も気にする必要がありません (Bash on GNU/Linux環境では/dev/fd/n
(実体はパイプ) を通じて入出力が行われます)。
prog1 < infile | tee >(prog3) | prog2
<(list)
と比べて、>(list)
のプロセス置換は利用頻度が圧倒的に少ないと思いますが、こういうときに利用できます。パイプを分岐したいユースケース自体もあまり多くありませんが、例えばネットワーク経由で大きなデータを取得して異なるパターンの集計や加工を行いたいとき等に、データ取得を1回で済ませて一時ファイルも作らずワンライナーできれいに片付けることができるので、シェル芸人にはきっと役立つでしょう。
プロセス置換の具体的なユースケースは、TLDPのAdvanced Bash-Scripting Guide等でもたくさん紹介されているので参考にしてみてください。
参考文献
- W. Richard Stevens, Stephen A. Rago (2013). Advanced Programming in the UNIX® Environment, Third Edition. Addison-Wesley Professional
- Mendel Cooper (2014). Advanced Bash-Scripting Guide
- Bash Reference Manual