LoginSignup
27
12

More than 5 years have passed since last update.

シェルスクリプトで複数のコマンド出力を結合する

Last updated at Posted at 2018-01-30

やりたいこと

SoftwareDesignのシェルスクリプト記事を読んでから、シェルスクリプトがちょっとブーム。
いっぱいパイプにつないで喜んでたら、ふと疑問が浮かんだ。
コマンド出力の分岐は伝家の宝刀teeコマンドがある。
じゃぁ結合は?

方法1 一時ファイルに書く

$ TMP=`tempfile`; echo hoge > $TMP; echo fuga >> $TMP; cat $TMP; rm $TMP

まぁ、できてるけども。。。

方法2 bashのプロセス置換を使う

$ cat <(echo hoge) <(echo fuga)
hoge
fuga

スマート。
でもbash限定。
そして出力が継続するコマンド(何て呼べばいいんだろう)に対してはうまく行かない。
(追記:"a continuous streaming command"と言うそうです。@7of9さん、ありがとうございます。)

方法3 fifoを使う

$ mkfifo /tmp/shout
$ echo hoge > /tmp/shout | echo fuga > /tmp/shout | cat /tmp/shout
hoge
fuga

fifoだと入力があるまでブロックしてくれるので、バックドア的な使い方ができる。
例えば、標準入出力しかI/FがないインタラクティブなCUIアプリ(QEMUのようなシミュレータとか)に対して、CIから自動テストのトリガをかける時などに使える。

1. CUIアプリ起動時に標準入力を/tmp/shuoutを経由するようにしておく
(CUIアプリの例として下記ではbashにしている)

$ mkfifo /tmp/shout
$ cat > /tmp/shout | cat /tmp/shout | bash
uname -r
4.13.0-32-generic

2.別のターミナルから、/tmp/shoutにコマンドを流しこむ

$ echo uname -r > /tmp/shout

3. 1.で起動したCUIアプリにコマンドが入力される
(今回の例ではbash上でコマンドが実行される)

4.13.0-32-generic

手順2.でnc -lkなどと繋げば他のホストから入力することも可能。
もちろんecho $'\cC' > /tmp/shoutなどとしたら制御文字を送りつけることもできる。

結論

bashで単発のコマンド出力を結合するときは、プロセス置換。
bashじゃない、または終わらないコマンド("a continuous streaming command")の出力を結合するときは、fifo。

雑感

シェルスクリプトは限られたコマンドを組み合わせて目的を達成するパズル的な楽しさがあるなー。

参考

27
12
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
12