众所周知,如何将一个进程的标准输出通过管道传输到另一个进程的标准输入中:
proc1 | proc2
但是如果我想将 proc1 的标准错误发送到 proc2 并将标准输出保留到其当前位置怎么办?您可能会认为
bash
会有一个类似于以下内容的命令:
proc1 2| proc2
但是,唉,没有。有什么办法可以做到这一点吗?
还有流程替代。这使得进程替代了文件。
您可以将
stderr
发送到文件,如下所示:
process1 2> file
但是您可以按如下方式替换文件的进程:
process1 2> >(process2)
这是一个具体示例,它将
stderr
发送到屏幕并附加到日志文件
sh myscript 2> >(tee -a errlog)
您可以使用以下技巧来交换
stdout
和stderr
。然后您只需使用常规管道功能即可。
( proc1 3>&1 1>&2- 2>&3- ) | proc2
假设
stdout
和 stderr
在开始时都指向同一个位置,这将为您提供所需的内容。
x>&y
位的作用是更改文件句柄x
,因此它现在将其数据发送到文件句柄y
当前指向的任何位置。对于我们的具体案例:
3>&1
创建一个 new 句柄 3
,它将输出到 current 句柄 1
(原始标准输出),只是为了将其保存在下面最后一个要点的某个地方。1>&2
修改句柄 1
(stdout)以输出到 current 句柄 2
(原始 stderr)。2>&3-
修改句柄2
(stderr)以输出到current句柄3
(原始标准输出),然后关闭句柄3
(通过末尾的-
)。这实际上是您在排序算法中看到的交换命令:
temp = value1;
value1 = value2;
value2 = temp;
Bash 4 有这个功能:
如果使用‘|&’,则command1的标准错误通过管道连接到command2的标准输入;它是 2>&1 | 的简写。标准错误的隐式重定向是在命令指定的任何重定向之后执行的。
zsh也有这个功能。
--
对于其他/较旧的 shell,只需明确输入为
第一个命令 2>&1 |其他命令
交换很棒,因为它解决了问题。万一您甚至不需要原始的标准输出,您可以这样做:
proc1 2>&1 1>/dev/null | proc2
顺序至关重要;你不会想要的:
proc1 >/dev/null 2>&1 | proc1
因为这会将所有内容重定向到
/dev/null
!
这些都没有真正起到很好的作用。我发现做你想做的事情的最好方法是:
(command < input > output) 2>&1 | less
这只适用于
command
不需要键盘输入的情况。例如:
(gzip -d < file.gz > file) 2>&1 | less
会将 gzip 错误放入 less
((回显一;回显 -e '二 错误' >&2) |wc) 2> >(wc)