Bashシェルコマンドのリダイレクトはどこに配置しますか? [コピー]

Bashシェルコマンドのリダイレクトはどこに配置しますか? [コピー]

重複の可能性:
注文リダイレクト

現在のシェルの入力と出力を独立してリダイレクトする以外に、exec >&2次のコマンドの動作に違いはありますか?

  1. echo -en "C\nB\nA\n" | sort 2>/dev/stdout >&2
  2. echo -en "C\nB\nA\n" 2>/dev/stdout >&2 | sort
  3. 2>/dev/stdout >&2 echo -en "C\nB\nA\n" | sort

上記のコマンドが同じであれば、好ましい変形は何ですか?

答え1

まず、簡単なコマンド(デフォルトでは、プログラム名の後にはいくつかのパラメータが続きます。)パラメータとリダイレクトの相対位置は重要ではありません。コマンド名の前にリダイレクトすることもできます。以下はすべて同じです。

foo --bar qux >out 2>err
foo >out --bar 2>err
>out 2>err foo --bar qux

(すべての可能性をリストしているわけではありません。)リダイレクトを最後に置くのが一般的なので、そうでなければ将来の読者は驚くかもしれません。しかし、これはスタイルの問題です。コマンドの前に入力リダイレクトを配置し、コマンドの後に出力リダイレクトを配置すると、特にパイプラインでの読み取り順序が処理順序と同じになるため、いくつかの利点があります。

<input.txt command1 | command2 | command3 >output.txt

command1 <input.txt | command2 …最初の処理ステップの後に原点を配置することとは対照的です。)

複合コマンドでは、リダイレクトを最後に配置する必要があります。たとえば、次のコードスニペットでは、リダイレクトを他の場所に配置することはできません。

while some_predicate; do some_action; done <in >out
{ command1; command2; } <in >out

複数のリダイレクトがある場合は重複する場合、つまり共通ファイル記述子がある場合は順序が重要です。バラより注文リダイレクト

パイプラインでは、リダイレクトはすべてのパイプラインコマンドに適用されます。あなたの例では、リダイレクトはsort(1)コマンドと(2,3)echoコマンドでのみ機能します。前述したように、(2)と(3)は同じです。

(2)と(3)では、出力はechoリダイレクト前に同じ位置で終了します。と書くと、echo -en "C\nB\nA\n" >&2 | sortパイプの左側にあるコマンドはstdoutに何も出力しないため、空のsortstdinが表示されます。

コマンドブロックを中括弧で囲み、コマンドブロックの入力または出力をリダイレクトできます。

{ command1 | command2; } 2>error.log

私はあなたが選択したリダイレクトがデモ目的にすぎないと仮定します。2>/dev/stdout >&2作成するのは複雑です2>&1(標準エラー(fd 2など)を現在の標準出力(fd 1など)がある場所にリダイレクトします)。

答え2

1は2、3とは異なります。 2と3は同じです。

バージョン 1 では、C\nB\nA\nに送信される FD 2 が元の宛先 ( ) で にマッピングされsort、その後、とにかく到着した FD 1 が に送信されます (やや無意味)。sortSTDERRSTDOUTSTDOUTsortSTDOUT

バージョン 2 および 3 では、echoFD 2 がSTDERR元の宛先 () からマッピングされたSTDOUT後、どうせ到着した FD 1 が 'STDOUTに送信されます。echoSTDOUT

機能的には、これらのコマンドのいずれかSTDERR

バージョン1では、echo何かをFD 2に出力するとFD 2に移動しますSTDERRが、バージョン2と3ではに移動しますSTDOUT(したがってパイプでも接続されますsort)。また、バージョン1ではsortFD 2に何かを送信するとに移動しますが、STDOUTバージョン2と3では対応する出力がに移動しますSTDERR

「好みのバリエーション」に関する限り、実際には次のようなものをさらに使用する必要がありechoますSTDERRsort

echo -en "C\nB\nA\n" 2>&1 | sort

これは、FD 1が既定で既に含まれており、STDOUTFD 2がファイル記述をその記述子にコピーできるようにするために機能します。

関連情報