159

众所周知,如何将一个进程的标准输出通过管道传输到另一个进程的标准输入:

proc1 | proc2

但是,如果我想将 proc1 的标准错误发送到 proc2 并将标准输出保留到其当前位置怎么办?你会认为bash会有一个类似的命令:

proc1 2| proc2

但是,唉,没有。有没有办法做到这一点?

4

5 回答 5

192

还有过程替换。这使得进程替代文件。
您可以stderr按如下方式发送到文件:

process1 2> file

但是您可以按如下方式替换文件的进程:

process1 2> >(process2)

这是一个发送stderr到屏幕并附加到日志文件的具体示例

sh myscript 2> >(tee -a errlog)
于 2012-03-27T11:28:26.943 回答
101

您可以使用以下技巧来交换 stdoutstderr. 然后,您只需使用常规管道功能。

( proc1 3>&1 1>&2- 2>&3- ) | proc2

提供stdout并且stderr在开始时都指向同一个地方,这将为您提供所需的东西。

x>&y位所做的是更改文件句柄x,因此它现在将其数据发送到文件句柄y当前指向的任何位置。对于我们的具体案例:

  • 3>&1创建一个句柄3,该句柄将输出到当前句柄1(原始标准输出),只是为了将其保存在下面的最后一个要点。
  • 1>&2修改句柄1(stdout) 以输出到当前句柄2(原始 stderr)。
  • 2>&3-修改句柄2(stderr)以输出到当前句柄3(原始标准输出),然后关闭句柄3(通过-末尾的)。

它实际上是您在排序算法中看到的交换命令:

temp   = value1;
value1 = value2;
value2 = temp;
于 2009-10-02T05:15:50.840 回答
79

Bash 4 有这个功能:

如果使用了`|&',则command1的标准错误通过管道连接到command2的标准输入;它是 2>&1 | 的简写。标准错误的这种隐式重定向在命令指定的任何重定向之后执行。

zsh 也有这个功能。

--

对于其他/较旧的外壳,只需将其明确输入为

第一个命令 2>&1 | 其他命令

于 2009-10-02T06:14:28.380 回答
32

交换很棒,因为它可以解决问题。万一您甚至不需要原始标准输出,您可以这样做:

proc1 2>&1 1>/dev/null | proc2

顺序至关重要;你不会想要:

proc1 >/dev/null 2>&1 | proc1

因为这会将所有内容重定向到/dev/null!

于 2011-12-16T14:24:50.763 回答
3

这些都不是真的很好用。我发现做你想做的最好的方法是:

(command < input > output) 2>&1 | less

这仅适用于command不需要键盘输入的情况。例如:

(gzip -d < file.gz > file) 2>&1 | less

会将 gzip 错误放入 less

于 2019-02-01T20:22:44.147 回答