所以我可以重定向到STDOUT和使用grep,但问题是,我不想原来的STDOUT内容。
所以,这一个不会做
cmd 2>&1 | grep pattern
因为它会混合原STDOUT和STDERR。
和这一个不工作,因为grep不读取STDERR输出:
cmd 1>/dev/null | grep pattern
但也是,这一个不会工作:
cmd 1>/dev/null 2>&1 | grep pattern
因为输出将完全为空,因为一切都写入/ dev / null。
但是必须有一个简单的方法吗?
你最后一个命令的原因:
cmd 1>/dev/null 2>&1 | grep pattern
不工作,源自重定向工作顺序的混乱。您希望最后引用的重定向应用于每个输出上的前一个,以便输出原始标准输出文件描述符(1)将转到/ dev / null,并输出到标准错误文件描述符(2)转到原始标准输出。
但是,这不是shell重定向如何工作。每个重定向通过关闭“源”并将“目标”复制到其中来重新映射文件描述符(参见dup(2)和close(2)的手册页)。这意味着在命令中,标准输出首先被/ dev / null替换,然后标准错误替换为标准输出,即/ dev / null。
什么工作:
因此,要获得所需的效果,您只需要逆转重定向。然后,您将有标准错误转到标准输出,原始标准输出转到/ dev / null:
cmd 2>&1 >/dev/null | grep pattern
(注意,1 before>是不必要的 – 对于输出重定向,标准输出是默认值)
附录:Charlie提到重定向到& – 关闭文件描述符。如果使用支持该扩展的交互式shell(bash和一些其他实现但不是全部,它是not standard),你也可以这样做:
cmd 2>&1 >&- | grep pattern
这可能更好 – 它可以节省一些时间,因为当命令尝试写入标准输出时,对写入的调用可能立即失败,而无需等待上下文切换到内核和驱动程序处理/ dev / null(取决于系统调用实现 – 一些可能在libc函数中捕获,一些也可能有/ dev / null的特殊处理)。如果有很多输出可以值得,并且它的输入更快。
这将主要工作,因为大多数程序不关心如果他们不能写入标准输出(谁真正检查printf的返回值),并不介意标准输出关闭。但是一些程序如果写入失败,可以使用失败代码释放 – 通常阻塞处理器,程序使用一些小心的I / O库或记录到stdandard输出。所以如果它不工作记住这是一个可能的原因,并尝试/ dev / null。