「リダイレクト」と「パイプ」で実際に何が行われているのかを考えると、物事を視覚化する方がはるかに簡単です。bashのリダイレクトとパイプは、プロセスファイル記述子0、1、および2が指す場所を変更する(/ proc / [pid] / fd / *を参照)ことを行います。
ときパイプや「|」演算子がコマンドラインに存在する場合、最初に発生するのは、bashがfifoを作成し、左側のコマンドのFD 1をこのfifoにポイントし、右側のコマンドのFD 0を同じfifoにポイントすることです。
次に、各サイドのリダイレクト演算子が左から右に評価され、記述子の重複が発生するたびに現在の設定が使用されます。パイプが最初に設定されたため、FD1(左側)とFD0(右側)は通常の状態から既に変更されており、これらの重複はその事実を反映しているため、これは重要です。
したがって、次のように入力すると、
command 2>&1 >/dev/null | grep 'something'
これが順番に起こります:
- パイプ(fifo)が作成されます。「コマンドFD1」はこのパイプを指しています。「grep FD0」もこのパイプを指しています
- 「コマンドFD2」は、「コマンドFD1」が現在指している場所(パイプ)を指します。
- 「コマンドFD1」は/ dev / nullを指しています
したがって、「コマンド」がそのFD 2(stderr)に書き込むすべての出力は、パイプに送られ、反対側の「grep」によって読み取られます。「コマンド」がFD 1(stdout)に書き込むすべての出力は、/ dev / nullに送られます。
代わりに、以下を実行します。
command >/dev/null 2>&1 | grep 'something'
ここで何が起こるかです:
- パイプが作成され、「コマンドFD 1」と「grep FD 0 "がそれを指している
- 「コマンドFD 1」は/ dev / nullを指しています
- 「コマンドFD 2」は、FD 1が現在指している場所を指します(/ dev / null)
したがって、「コマンド」からのすべてのstdoutおよびstderrは/ dev / nullに移動します。パイプには何も入らないため、「grep」は画面に何も表示せずに終了します。
また、リダイレクト(ファイル記述子)は、読み取り専用(<)、書き込み専用(>)、または読み取り/書き込み(<>)にできることに注意してください。
最後のメモ。プログラムがFD1またはFD2に何かを書き込むかどうかは、完全にプログラマ次第です。エラーメッセージはFD 2に送られ、通常の出力はFD 1に送られるべきであるとプログラミングの慣習で規定されていますが、この2つを混ぜたり、規則を無視したずさんなプログラミングを見つけたりすることがよくあります。