在 STDERR 之前显示 STDOUT?

MeO*_*eOw 9 shell bash io-redirection stdout stderr

我是 bash 新手,我一生都无法弄清楚如何运行某个命令,假设./fff并在 stderr 之前打印常规标准输出(我自己对含义感到困惑)

例如

$ 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
Run Code Online (Sandbox Code Playgroud)

需要打印如下:

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
Run Code Online (Sandbox Code Playgroud)

我知道我需要首先将我的输出重定向到一个文件,然后将错误附加到同一个文件中,但是这是我得到的输出

$ 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
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 18

无论如何,您都需要将 stderr 输出保存在某处才能在最后显示它。

想到一个文件

fff 2> file; cat file >&2
Run Code Online (Sandbox Code Playgroud)

内存(此处使用spongefrom moreutils):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
Run Code Online (Sandbox Code Playgroud)
  • {...} 3>&1: 在{...}文件描述符 (fd) 中 3 指向与原始标准输出相同的资源(因此我们可以使用它来恢复 的标准输出fff)。
  • fff <redirs> | sponge <redirs>,fffsponge同时开始(<redirs>独立应用),fff的 stdout 进入管道,而sponge的 stdin 是管道的另一端。
  • 2>&1: fd 2 of fff(stderr) 指向与 1: 相同的东西:此时的管道,因此fff错误sponge通过该管道。
  • >&3:现在标准输出指向原始标准输出(重定向回原来的状态)
  • 3>&-: 我们关闭fff不需要的fd 2
  • sponge累积其输入并仅>&2在其 stdin 上检测到 eof后才显示它(在其 stdout 上已重定向到与 stderr 相同的资源)(假设是在fff终止时并已将其所有输出写入其 stdout)。

如果sponge未安装,您可以将其替换为perl -0777 -pe ''. 使用-pe ''perl从其输入中一次读取一条记录并将其写入标准输出。-0777是 slurp 模式,其中(在这种情况下只有一个)记录是整个输入。

  • @MeOw:没关系,但是,正如 Stéphane 答案的第三行所示,您不需要保存标准输出;只需执行`cat foo nofile foo nofile foo 2&gt; ferr.txt; 猫ferr.txt`。(而且您可能不想使用`&gt;&gt;`。)此外,Stéphane 提出了一个很好的观点,即您应该执行`cat ferr.txt &gt;&amp;2` 将stderr 信息*写入*stderr。 (2认同)