とりあえずシェルのリダイレクトを「こわいものなし」というくらい完全に理解しよう - 檜山正幸のキマイラ飼育記を読んでなんとなくわかったつもりでパイプとかリダイレクトとかがちょっと理解した。 - ・・・tohokuaikiのチラシの裏(それ図解できたらいいなぁ)って書いたけど、シェルのリダイレクトの補遺 - 檜山正幸のキマイラ飼育記でちょい突っ込みをいただいたので、自分で分かるように図解してみた。
- まず、準備
前回は、標準入力とか標準出力について「んー、ファイルディスクリプタの0とかにデフォルトで付いてるやつ?」とか思ってたくらいだったけど、そこんところもう一回ちゃんと考えてみると、
- コマンドと直結しているものが標準(入力|出力|エラー出力)なんだ
と思った。
で、あとひとつ、これはトラックバックでいただいた点として
- フツーにファイルからも入力できるし、出力できるよ
って言う点。そりゃそうだ。C使ってて、ファイルポインタ使うもんね。ということで、ここまでの登場人物をまとめてみるとこんな感じ。
- Shell
- Shellで使うコマンド(grep/find/cat/...)
- コマンドが使う入出力経路(STDIN/STDOUT/STDERR/*fp)
- コマンド→Shellを通じた入出力の落としどころであるデバイス(画面とかファイル)
- 話題の中心、ファイルディスクリプタ
- 操作する人
で、フツーのgrepを使ってみた場合が、
$ grep ^a infile
この場合、なにもリダイレクトしてないので、ファイルディスクリプタはデフォルトのデバイスにそのコマンドの結果を渡す。
次に、ごく簡単なリダイレクトを使った場合。
$ grep ^a < infile > outfile
この場合は、grepの標準入力とinfileをファイルディスクリプタの0がつないでくれるようになって、grepの標準出力とoutfileをファイルディスクリプタの1がつないでくれる。grepの標準(入力|出力)と強調。
リダイレクトにより、画面ではなくファイルにその入出力がゆだねられることになった。
最後、パイプとリダイレクトの代入を使った例
$ cat infile | grep ^a > outfile 2>&1
パイプ・・はまさにパイプで、ようやくその名前と役割がいかにぴったりなのかが理解できた気がする。ようするに、コマンドAの出力とコマンドBの入力をつないでやるってこと。文字にすると、「そりゃそうじゃん」って気になるし、コマンドラインを見ていても「あー、前の結果を受けてるね」って気になるけど、図にするまでは正直「あー、パイプ」っていう感じは沸かなかった。
あとは、どんなに複雑でもコレの繰り返しだし。あ、コマンド区切り「;」とかよく分からんね。使ったことないし。
しかし、こうやって図にすると分かりやすいな。これがスーツの仕事なんだよ。うん。