web-dev-qa-db-ja.com

リダイレクトの順序

コンピュータがこのコマンドをどのように読み取るか、私にはよくわかりません。

cat file1 file2 1> file.txt 2>&1

私が理解しているのであれば、2>&1は標準エラーを標準出力にリダイレクトするだけです。

そのロジックにより、コマンドは次のように読み上げます。

  1. ファイルfile1file2を連結します。

  2. この操作からstdoutfile.txtに送信します。

  3. stderrstdoutに送信します。

  4. 終わり?

コンピュータが何をしているかわかりません。私の論理では、コマンドは

cat file1 file2 2>&1 > file.txt

しかし、これは正しくありません。

40
iDontKnowBetter

割り当てを使用することを考える方が簡単だと思います。

  • > のようなものです =
  • & のようなものです $

あなたは

1 = /dev/tty
2 = /dev/tty

次に、最初の例、1> file.txt 2>&1、する

1 = file.txt
2 = $1           # and currently $1 = file.txt

あなたと一緒に

1 = file.txt
2 = file.txt

もしあなたがそれを逆にしたなら、再びあなたは

1 = /dev/tty
2 = /dev/tty

次に2>&1 > file.txt

2 = $1           # and currently $1 = /dev/tty
1 = file.txt

最終結果は

1 = file.txt
2 = /dev/tty

リダイレクトしたのはstdoutではなくstderrだけです。

58
Mikel

リダイレクションの順序は重要であり、それらを読む必要があります左から右

例えば: command 2>&1 >somefile 手段:

  1. リダイレクトstderr(つまり2)をstdoutの-​​current宛先に(この時点で端末).
  2. 次に、stdoutを変更してsomefileに移動します。

したがって、この場合、stderrはターミナルに行き、stdoutはファイルに行きますが、これはおそらく望んでいないことです。

一方、 command >somefile 2>&1 手段:

  1. stdoutsomefileにリダイレクト
  2. 次に、stderrstdoutsomefile)と同じ宛先にリダイレクトします。

この最後のケースでは、stderrstdoutの両方がsomefileに移動します。

13
cat file1 file2 1> file.txt 2>&1

>&実際には複製を意味します。dupシステムコールを使用して、新しいファイル記述子をすでに開いているファイルにマッピングします。

したがって、(実際にはbashで)最初に新しいstdoutを開いてから、「現在設定されているstdoutにstderrをリダイレクトする」と言う必要があります。

4
X Tian