私は読んでいます。この文書リダイレクトおよびファイル記述子に関する次の例が提供されます。
ls > dirlist 2>&1
標準出力と標準エラーをファイルのディレクトリリストに送信しますが、コマンドは
ls 2>&1 > dirlist
標準出力のみが dirlist として指定されます。これはプログラマにとって便利なオプションです。
これらの例は間違っていますか?私の考えでは第二たとえば、「標準出力と標準エラーをファイルのディレクトリリストに直接割り当てます」最初たとえば、「ディレクトリリストにのみ標準出力を送信します。」
私が間違っている場合(...おそらく...)、誰かがこの2つの例の論理を明確に説明できますか?
答え1
n>&m
まず構文を知る必要があります。これはコピー操作です。すなわち、mはnにコピーされる。セクションを見る「3.6.8 ファイル記述子のコピー」。
この記事を読んで、私と同じ質問がありました。だから私はあなたにそれを説明しようとすることができます:
ls > dirlist 2>&1
上記のコマンドを使用して、まず出力をdirlistにリダイレクトします> dirlist
。 2>&1
ファイル記述子 1 を 2 にコピーすること、つまり fd2 を fd1 のコピーにすることを示します。 fd1はすでにdirlistを指しているので、fd2をfd1のコピーにすることはfd2もdirlistを指すことを意味します。結果はfd1->dirlist、fd2->dirlistです。
ls 2>&1 > dirlist
このようにして、まずfd2をfd1のコピーにします。 fd1はまだターミナルなので、fd2->ターミナルです。次に、fd1をディレクトリリストにリダイレクトします。結果は fd2 -> 端末、fd1->dirlist です。
答え2
方向は左から右に処理されます。
ls > dirlist 2>&1
シェルが最終的に次のシステムコールを実行してlsに変わります(簡潔にするためにエラーチェックは省略されます)。
/* Handle > dirlist */
int temp_fd = open("dirlist",O_WR); /* Open dirlist for output */
dup2(temp_fd, 1); /* Make file descriptor 1 (stdout) point to dirlist */
close(temp_fd); /* Don't need this other file descriptor for dirlist */
/* Handle 2>&1 */
dup2(1,2); /* Make fd 2 be a copy of fd 1, which points to dirlist */
したがって、まずfd 1を変更してからfd 2を変更します。
代わりに、ls 2>&1> dirlistは
/* Handle 2>&1 */
dup2(1,2); /* Make fd 2 be a copy of fd 1, the original stdout */
/* Handle > dirlist */
int temp_fd = open("dirlist",O_WR); /* Open dirlist for output */
dup2(temp_fd, 1); /* Make file descriptor 1 (stdout) point to dirlist */
close(temp_fd); /* Don't need this other file descriptor for dirlist */
それを見るもう一つの方法は宿題として見ることです。もともとfd1 = initial_stdoutの場合
/* ls > dirlist 2>&1 */
fd1=to_dirlist
fd2=fd1 (i.e. to_dirlist)
/* ls 2>&1 > dirlist */
fd2=fd1 (i.e. initial_stdout)
fd1=to_dirlist.
copy by value
または代わりにと言うこともできますcopy by reference
。