我是 bash 新手,我一生都无法弄清楚如何运行某个命令,假设./fff
并在 stderr 之前打印常规 stdouts (我自己对含义感到困惑)
例如
$ 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
答案1
你需要抓住无论如何,stderr 输出都能够在最后显示它。
A文件我想到:
fff 2> file; cat file >&2
或者记忆(这里使用sponge
from moreutils
):
{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
{...} 3>&1
: 在{...}
文件描述符 (fd) 3 内指向与原来的标准输出(因此我们可以使用它来恢复标准输出fff
)。fff <redirs> | sponge <redirs>
,fff
并sponge
同时开始(<redirs>
独立应用),fff
的 stdout 进入管道,sponge
的 stdin 是管道的另一端。2>&1
: (stderr) 的 fd 2fff
指向与 1: 此时的管道相同的东西,因此fff
错误将sponge
通过该管道进行。>&3
:现在标准输出指向原始标准输出(重定向回原来的位置)3>&-
:我们关闭fff
不需要的fd 3sponge
>&2
累积其输入并仅在其 stdin 上检测到 eof 后(假设在fff
终止并已将其所有输出写入其 stdout 上)后才显示它(在其 stdout 上,该 stdout 已重定向到与 stderr 相同的资源)。
如果sponge
没有安装,可以用 替换perl -0777 -pe ''
。使用 时-pe ''
,perl
一次从输入中读取一条记录并将其写入标准输出。-0777
是 slurp 模式,其中(在这种情况下只有一个)记录是整个输入。