21

i/o シェルのリダイレクトで遊んでいます。私が試したコマンド(bashで):

ls -al *.xyz 2>&1 1> files.lst

ls -al *.xyz 1> files.lst 2>&1

*.xyz現在のフォルダーにはファイルがありません。

これらのコマンドは、さまざまな結果をもたらします。最初のコマンドはls: *.xyz: No such file or directory、画面にエラー メッセージを表示します。しかし、2 番目のものは、このエラー メッセージをファイルに出力します。最初のコマンドが err 出力をファイルに書き込めなかったのはなぜですか?

4

5 に答える 5

42

Bashマニュアルには、順序が重要であることを示す明確な例(あなたのものに似ています)があり、違いも説明しています。抜粋された関連部分は次のとおりです(強調は私のものです):

リダイレクトの順序は重要であることに注意してください。たとえば、コマンド

ls >ディレクトリリスト2>&1

コマンドは、標準出力 (ファイル記述子 1) と標準エラー (ファイル記述子 2) の両方をファイルdirlistに送ります。

ls 2>&1 >ディレクトリリスト

標準出力がdirlistにリダイレクトされる前に、標準エラーは標準出力のコピーが作成されたため、標準出力のみをファイルdirlistに送信します。

この投稿では、POSIX の観点から説明します。

混乱は、重要な違いが原因で発生します。左のオペランド ( ) を右のオペランド ( ) に向けるのではなく、右のオペランドのコピーを作成して左に代入することによって>リダイレクトします。概念的には、参照ではなくコピーによる代入です。stderrstdout

したがって、左から右への読み取りは、これが Bash によって解釈される方法です: file へのls > dirlist 2>&1リダイレクトを意味し、その後、現在のもの (既に file )へのリダイレクトが続きます。ただし、現在のもの(画面/端末)にリダイレクトしてから、にリダイレクトします。stdoutdirliststderrstdoutdirlistls 2>&1 > dirliststderrstdoutstdoutdirlist

于 2014-08-12T08:28:27.650 に答える
18

リダイレクトは次のとおりです。

  • 左から右に処理されます。
  • 繰り返し解釈:
    • 以前のリダイレクトはのリダイレクトに影響を与える可能性があります。
      • 以前のリダイレクトが特定のストリーム ( 1stdout (デフォルト) や2stderr などのファイル記述子番号によって識別される) をリダイレクトした場合、そのストリームを対象とするその後のリダイレクトは、既にリダイレクトされたバージョンを参照します。
    • ただし、その逆はありません。後のリダイレクトは、以前のリダイレクトのターゲットに遡及的な影響を与えません。
      • たとえば、以前のリダイレクトでファイル記述子1をターゲットとして指定した場合、後でリダイレクトされたとしても、その時点でロックされていること1を意味します。1
  • ただし、すべてのリダイレクトが行われるまで出力は実際には送信されず、コマンドの実行が開始される前にリダイレクト対象の出力ファイルが作成または切り捨てられることに注意してください(これが、出力を読み取ってリダイレクトできない理由です)。単一のコマンドで同じファイル)。

質問の例に適用:

  • >file 2>&1:

    • >file 最初にstdout ( file descriptor 、ファイル記述子番号を1プレフィックスとして付けないことによって暗示される) を出力ファイルにリダイレクトします>file
    • 2>&1 次に、 stderr ( 2) をリダイレクト済みのstdout ( 1) にリダイレクトします。
    • 正味の効果は、両方の元のストリームがfile.
  • 2>&1 >file:

    • 2>&1最初に stderr を当時の元のstdout にリダイレクトします。ファイル記述子2はそれ以上のリダイレクトに関与しないため、stderr 出力は、その時点で定義されていた stdout に出力されます。つまり、これが最初のリダイレクトである 場合、元のstdout です。
      • 技術的には、元の stdout ファイル記述子は複製され、その複製は stderr が参照するものであり、後で stdout のリダイレクトの影響を受けない理由を説明しています。
    • >file次に、元の stdout をfile- にリダイレクトしますが、既にロックインされている stderr のリダイレクトには影響しません。
    • 最終的な効果は、stdout に直接送信された出力のみが にキャプチャされfile、stderr に送信された出力は (元の、リダイレクトされていない) stdout に出力されることです。
于 2015-12-17T04:08:23.930 に答える