web-dev-qa-db-ja.com

STDERRの前にSTDOUTを表示しますか?

私はbashを使い始めたばかりで、特定のコマンドを実行する方法を理解することができません。_./fff_で、stderrの前に通常のstdoutを出力するとします(自分自身の意味について混乱しています)。

例えば

_$ printf "I am a\ndrill\n" > fff; 
$ cat fff nofile fff nofile fff

I am a
drill
cat: nofile: No such file or directory
I am a
drill
cat: nofile: No such file or directory
I am a
drill
_

次のように印刷する必要があります:

_I am a
drill
I am a
drill
I am a
drill
cat: nofile: No such file or directory
cat: nofile: No such file or directory
_

最初に出力をファイルにリダイレクトしてから、同じファイルにエラーを追加する必要があることを理解していますが、これは私が取得する出力です

_$ cat ./foo nofile ./foo nofile ./foo <<< $(touch fin) > see 2>> see 

I am a
drill
I am a
drill
I am a
drill
ectory
cat: nofile: No such file or directory
_
9
MeOw

holdとにかくstderrの出力をどこかに表示して、最後に表示できるようにする必要があります。

ファイルが思い浮かびます:

fff 2> file; cat file >&2

またはmemory(ここではspongemoreutilsを使用しています):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
  • {...} 3>&1{...}ファイル記述子内(fd)3はoriginal stdout(fffのstdoutを復元するために使用できる)と同じリソースを指します。
  • fff <redirs> | sponge <redirs>fffおよびspongeは同時に開始され(<redirs>は個別に適用されます)、fffのstdoutはパイプに行き、spongeのstdinはパイプのもう一方の端ですパイプ。
  • 2>&1:fd 2 of fff(stderr)は、1と同じことを指します。このポイントのパイプなので、fffのエラーはそのパイプを介してspongeに移動します。
  • >&3:stdoutが元のstdoutを指すようになりました(元のstdoutにリダイレクトされます)
  • 3>&-fffには不要なfd 2を閉じます
  • spongeは、その入力を蓄積し、そのstdinでeofを検出した後(fffが終了したと想定)にのみ、(>&2でstderrと同じリソースにリダイレクトされたstdoutに)表示します。そして、すべての出力をstdoutに既に書き込んでいます)。

spongeがインストールされていない場合は、Perl -0777 -pe ''で置き換えることができます。 -pe ''を使用すると、Perlは入力から一度に1つのレコードを読み取り、stdoutに書き込みます。 -0777は、(その場合は1つだけ)レコードが入力全体であるSlurpモードです。

18