Bashのマニュアルのリダイレクトセクションにあるタイプミスですか?

Bashのマニュアルのリダイレクトセクションにあるタイプミスですか?
Note that the order of redirections is significant.  For example, the command

          ls > dirlist 2>&1

   directs both standard output and standard error to the file dirlist, 
   while the command

          ls 2>&1 > dirlist

   directs  only  the  standard  output  to  file  dirlist,  because the 
   standard error was duplicated from the standard output before the standard
   output was redirected to dirlist.

今、最後の部分が私を混乱させます。この場合、標準エラーが端末に出力され、STDOUT がディレクトリリストファイルに移動されます。そのようなことが起こりますが、マニュアルを理解するわけではありません。

「標準出力がディレクトリリストにリダイレクトされた後、標準エラーが標準出力からコピーされるためです」と言う必要があるようです。 STDOUTがファイルに渡される前にSTDERRがSTDOUTに転送された場合、ファイルにSTDOUTとSTDERRは含まれませんか?

誰でもこの問題を解決するのに役立ちますか?私の読解力が足りないせいか?この文脈では、「繰り返し」という言葉を使うのは私にとっては少し奇妙に見えます。たぶんこれは私を混乱させるかもしれません。

ベストアンサー1

コピーここで本当に重要な部分です。

リダイレクトされる前に、ファイル記述子がどこに行くかを見てみましょう。これは通常現在の端末です。たとえば、次のようになります。

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

リダイレクトなしで呼び出すと、ls -l出力とエラーメッセージが私の端末に移動します/dev/pts/1

STDOUTまずファイル()にリダイレクトすると、ls -l > dirlist次のようになります。

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

いつ私たちがそれからSTDERRリダイレクトコピーSTDOUTls -l > dirlist 2>&1)のファイル記述子は、STDERR次のコピーに移動します/home/bon/dirlist

STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist

私たちが望むなら最初リダイレクトするファイル記述子()のコピーSTDERRSTDOUTls -l 2>&1

STDOUT ---> /dev/pts/1
STDERR ---> /dev/pts/1

そしてそれから STDOUTファイル(ls -l 2>&1 > dirlist)について以下を取得します。

STDOUT ---> /home/bon/dirlist
STDERR ---> /dev/pts/1

この時点でSTDERR私たちはまだターミナルに行かなければなりません。

ご覧のとおり、マニュアルページの順序は正しいです。


テストリダイレクト

今すぐテストしてみましょう。を使用すると、現在のプロセスがどこに行くか(fd 1を使用)と(fd 2を使用)をls -l /proc/$$/fd/確認できます。STDOUTSTDERR

$ ls -l /proc/$$/fd/
total 0
lrwx------ 1 bon bon 64 Jul 24 18:19 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 07:41 2 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 18:19 255 -> /dev/pts/1

ファイル記述子が指す場所を表示する小さなシェルスクリプトを作成しましょう。これにより、lsコールシェルのリダイレクトを含む、常にコール時にステータスを取得できます。

$ cat > lookfd.sh
#!/bin/sh
ls -l /proc/$$/fd/
^D
$ chmod +x lookfd.sh

(を使用すると、CtrlDファイル終了文字を送信してからcat読み取りコマンドを停止できますSTDIN。)

次に、さまざまなリダイレクトの組み合わせを使用してこのスクリプトを呼び出します。

$ ./lookfd.sh 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:08 0 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:08 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:08 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh 2>&1 > foo.out
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:10 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:10 1 -> /home/bon/foo.out
lrwx------ 1 bon bon 64 Jul 24 19:10 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:10 255 -> /home/bon/lookfd.sh
$ ./lookfd.sh > foo.out 2>&1
$ cat foo.out 
total 0
lrwx------ 1 bon bon 64 Jul 24 19:11 0 -> /dev/pts/1
l-wx------ 1 bon bon 64 Jul 24 19:11 1 -> /home/bon/foo.out
l-wx------ 1 bon bon 64 Jul 24 19:11 2 -> /home/bon/foo.out
lr-x------ 1 bon bon 64 Jul 24 19:11 255 -> /home/bon/lookfd.sh

STDOUTファイル記述子1(の場合)と2(の場合)が異なることを確認できますSTDERR。楽しみにリダイレクトしSTDINて結果を見ることもできます。

$ ./lookfd.sh < /dev/zero
total 0
lr-x------ 1 bon bon 64 Jul 24 19:18 0 -> /dev/zero
lrwx------ 1 bon bon 64 Jul 24 19:18 1 -> /dev/pts/1
lrwx------ 1 bon bon 64 Jul 24 19:18 2 -> /dev/pts/1
lr-x------ 1 bon bon 64 Jul 24 19:18 255 -> /home/bon/lookfd.sh

(読者に残った質問:ファイル記述子255はどこを指していますか?;-))

おすすめ記事