
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
リダイレクトコピーSTDOUT
(ls -l > dirlist 2>&1
)のファイル記述子は、STDERR
次のコピーに移動します/home/bon/dirlist
。
STDOUT ---> /home/bon/dirlist
STDERR ---> /home/bon/dirlist
私たちが望むなら最初リダイレクトするファイル記述子()のコピーSTDERR
:STDOUT
ls -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/
確認できます。STDOUT
STDERR
$ 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はどこを指していますか?;-))
答え2
いいえ、指示は正しいです。
最初に1がターミナルを指し、2度ターミナルを指す場合:
command 2>&1 1>somewhere
リダイレクト評価は左から右に行われます。
したがって、最初に評価2>&1
してから、1
fdが指す内容(ファイル記述子、通常は/ dev / ttyなど)をthe terminal
fdにコピーします2
。
したがって、この時点でfdは、fdがかつて()を指していた2
位置を指します。1
the terminal
その後、そのセクションを評価して1>somewhere
fdのファイル記述子をコピーします(したがって、この時点でfdは現在指され、fdはまだポイントされます)。somewhere
1
1
somewhere
2
the terminal
したがって、1が変更される前に1から2がコピーされたので、1を「どこかに」印刷し、2を端末に印刷する。
別の順序:
command 1>somewhere 2>&1
まずfd1
をにリダイレクトsomewhere
してから、同じ参照をfd 2にコピーするので、最終的に2度を指しますsomewhere
。しかし、今から彼らはもはや「連絡」しません。それぞれはまだ個別にリダイレクトできます。
前任者:
command 1>somewhere 2>&1
exec 2>/dev/null
最後に fd は1
を指し、somewhere
fd は2
次に向かいます。/dev/null
fdの一般名1
はSTDOUT(標準出力)、fdの一般名2
はSTDERR(標準エラー、通常はSTDOUTを妨げずにエラーを表示するために使用されるため)です。
答え3
ここで混乱している部分は、stderrをstdoutにリダイレクトすると、実際に2つのストリームをリンクするという誤解だと思います。
これは完全に合理的な考えですが、2>&1
stderrに書くときに起こるのは、stdoutが何を書いているのかを見て、同じ場所自体に書き込むことです。したがって、後でstdoutに他の場所に書き込むように指示すると、移動されたstderrのターゲットには影響しません。
私はこれが少し直観にずれていると思いますが、これがうまくいく方法です。投稿したい場所を設定し、すべての人に「私をコピーしてください」と言ってください。その内容が明確になることを願っています...
答え4
コピー...
重要だがもっと重要なこと多くの混乱の源。本当に簡単です。この答えは単に「根本的な」例です。
許容される回答は良いですが、長すぎて「繰り返し」を強調しています。
質問は賢明に次のように終わります。
これ繰り返しという単語の使用このような場合は、ちょっと変だと思います。たぶんこれは私を混乱させるかもしれません。
私はbash表記を使用し、ファイルが「1」と「2」を処理するように「one」と「two」変数を定義しました。 (出力)リダイレクト演算子>
は割り当てです=
。&
そして$
「価値」を意味します。
man bash はい(デフォルトは「1」を追加)
ls 1>dirlist 2>&1 # both to dirlist
ls 2>&1 1>dirlist # 1 to dirlist, 2 stays on tty/screen
次のようになります。
one=dirlist two=$one
そして
two=$one one=dirlist
私や他の人にとって、これは自動的に行われるわけではありません。最初の行は出て、両方$one
とも$two
「dirlist」を含みます。確かに。
2行目は無駄な割り当てで始まります。どちらの定義も「TTY」で始まります(やや象徴的に)。方向;この割り当ては値を変更せず、変数(ファイルハンドルなど)の場合、魔法のようにリンクされていません。変数はtwo
次の影響を受けませんone=dirlist
。当然じゃない。
誰か(6年前)「コピー」または「複製」を「指す」に変えようと提案した後、悟りました。それも混乱するでしょう。
そのような複製やポインタの意味論は必要ありません。おそらくもっと注意が必要なのはアンパサンドです。演算子/トークン/何でもの「値」です。
素晴らしい仕事数を得る方法を探している場合のみ快適、「完了」メッセージとボーナスとして「2」というファイルが表示されたら、次のことができます。
ls 1>2& 2>/dev/null
「と自然に読まれる。copy"/"duplicate" 1を2に設定し、両方ともnullに設定します。。しかし、アイデアが間違っていて構文が間違っています。 (ただし、構文エラーはなく、有効)
正しい計画方法は、どちらか一方をnullにリダイレクトし、もう一方を同じ場所にリダイレクトすることです。
ls 1>/dev/null 2>&1
# or
ls 2>/dev/null 1>&2
(前の「1」は省略可能)
(わかりました。acc.Aは長すぎませんが、リストが多すぎます。可視化はとても良いですが、説明はあまり良くありません。)