名前付きパイプ

shellで名前付きパイプを使うには mkfifo を使う(mknodでもできるらしい)

  1. 名前付きパイプの生成
  2. 読み込み専用で開く
  3. 書き込みを開始する
  4. 閉じる

ここで、注意。
読み込み専用で名前付きパイプを開いたら、書き込みが閉じられるまで、その後の処理がブロックされます。
逆に、書き込み専用で開いたら、読み込みが取じられるまで、その後の処理がブロックされてしまいます。
これは、ターミナルを二つ用意し、片方で以下を実行

mkfifo /tmp/test_fifo
cat /tmp/test_fifo | perl -nle "s/^/\[\[/;s/$/\]\]/g;print" 

# このとき、何も表示されず、入力を受けつけない状態になる

もう片方のターミナルで

ls > /tmp/test_fifo

とすると、書き込み処理が終了する為、
先のターミナルのブロックされていた処理が実行されることになる。
(カレントディレクトリのファイル名及びディレクトリ名が「」と「」で囲まれる)
/tmp/test_fifoがプロセスの橋渡しをしているわけです。

というわけで、こんなの作ってみました。
毎度面白くない例ですみません。

_test1(){
  # 標準入力を受けとって何らかの処理をする
  while read n
  do
    echo "[[$n]]" 
  done
}

_test2(){
  # 標準入力を受けとって何らかの処理をする
  while read n
  do
    echo "{{$n}}"
  done
}

# 名前付きパイプを作成し、バックグラウンドで監視。書き込みがあれば指定したコマンドを実行
mkfifo /tmp/test1_$$
cat /tmp/test1_$$ | _test1 &

mkfifo /tmp/test2_$$
cat /tmp/test2_$$ | _test2 &

# 名前付きパイプにそれぞれ書き込みを行う
for i in *
do
  echo $i >&3
  echo $i >&4
done 3>/tmp/test1_$$ 4>/tmp/test2_$$

Linuxで実行すれば、バックグラウンド処理になっているため、_test1と_test2の出力がまざってしまうけど、
OSXでは出力がまざらない。なぜかは未調査。

[追記]この方法で実行すると、_test1 か _test2のどちらかでエラーが発生した場合両方の処理が停止してしまうようだ。