Bash 如何将STDERR重定向到STDOUT,而忽略原始STDOUT?

Bash 如何将STDERR重定向到STDOUT,而忽略原始STDOUT?,bash,redirect,stdout,Bash,Redirect,Stdout,我有一个程序,它的STDERR输出我想检查并运行grep等 因此,我可以将其重定向到STDOUT并使用grep,但问题是,我不想要原始STDOUT内容 所以,这个不行 cmd 2>&1 | grep pattern 因为它将混合原始标准输出和标准输出 因为grep不读取STDERR的输出,所以这个不起作用: cmd 1>/dev/null | grep pattern 但是,这一个也不起作用: cmd 1>/dev/null 2>&1 | grep p

我有一个程序,它的
STDERR
输出我想检查并运行
grep

因此,我可以将其重定向到
STDOUT
并使用grep,但问题是,我不想要原始
STDOUT
内容

所以,这个不行

cmd 2>&1 | grep pattern
因为它将混合原始标准输出和标准输出

因为grep不读取STDERR的输出,所以这个不起作用:

cmd 1>/dev/null | grep pattern
但是,这一个也不起作用:

cmd 1>/dev/null 2>&1 | grep pattern
因为输出将完全为空,因为所有内容都写入
/dev/null

但是必须有一个简单的方法来完成它?

首先关闭STDOUT:

1>&-, >&-

请看。

我会尝试一些简单的方法,比如:

cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file
什么不起作用: 您引用上一条命令的原因:

cmd 1>/dev/null 2>&1 | grep pattern
不起作用,源于对重定向工作顺序的混淆。您希望最后引用的重定向应用于每个输出上它之前的重定向,以便原始标准输出文件描述符(1)的输出将转到/dev/null,而标准错误文件描述符(2)的输出将转到原始标准输出

但是,shell重定向不是这样工作的。每次重定向都会通过关闭“源”并将“目标”复制到其中(请参见
dup(2)
close(2)
man
页面),从而“重新映射”文件描述符。这意味着在命令中,标准输出首先被替换为
/dev/null
,然后标准错误被替换为标准输出,标准输出已经是
/dev/null

工作原理: 因此,要获得所需的效果,只需反转重定向即可。然后将标准错误转到标准输出,原始标准输出转到
/dev/null

cmd 2>&1 >/dev/null | grep pattern
(请注意,
>
之前的
1
是不必要的-对于输出重定向,标准输出是默认值)


附录:Charlie提到重定向到
&-
关闭文件描述符。如果使用支持该扩展的交互式shell(
bash
和其他一些实现,但不是全部,而是全部),您也可以这样做:

cmd 2>&1 >&- | grep pattern
这可能更好—它可以节省一些时间,因为当命令尝试写入标准输出时,
write
调用可能会立即失败,而无需等待上下文切换到内核和驱动程序处理
/dev/null
(取决于系统调用实现-有些可能在
libc
函数中捕捉到这一点,有些可能还具有对
/dev/null
的特殊处理)。如果有大量值得输入的输出,则可以更快地输入


这将主要起作用,因为大多数程序都不关心是否无法写入标准输出(谁真正检查
printf
?)的返回值)并且不会介意标准输出被关闭。但是,如果
写入
失败,一些程序可能会带着故障代码退出—通常会阻塞处理器,程序使用一些小心的库进行I/O或记录到标准输出。因此,如果它不起作用,请记住这是一个可能的原因,并尝试
/dev/null

Uhmm,您确定吗这就可以满足OP的要求了?对我来说似乎不行。如果你先关闭stdout,就没有办法将stderr重定向到它。好的,基于此,我发现这是有效的:2>&1>&-。也许你可以更新答案,因为在当前编写的时候,你可能会尝试以下方法:>&-2>&1,这是无效的。是的,那样(在重定向后关闭它)它可以工作,而且在受支持的情况下,有时比使用/dev/null更好,因为您可以在写操作时进行保存—我将更新我的答案以说明这一点,但在sh中显然不是标准的。关闭stdout,而不是发送到/dev/null,只有当写入stdout的命令忽略了写入时的错误时才起作用——这是对C编程的一个悲哀的评论,事实上,大多数时候,程序会忽略这些错误。@Charlie Martin。对,它被标记为bash,答案可能是好的。我不这么认为对bash的扩展了解得太多了,所以我在这里学到了一些新东西:-)选择的答案表明这是不必要的。你在第二部分中使用cat是无缘无故的。由于存在诊断输出,因此命令很有可能返回错误状态,&&将不会有帮助。我建议删除这一点。也考虑输出可能非常大,而CAT只会在最后看到GRIP,如果没有足够的空间写入临时文件,则会花费更多的时间,并且失败。除非您以后需要随机访问输出,否则最好使用“动态”管道。很棒的工作!毫无疑问,每当我需要它的时候,我都会一遍又一遍地回到这个页面来查找它。