什么不起作用:
您引用最后一个命令的原因:
cmd 1>/dev/null 2>&1 | grep pattern
不起作用,源于重定向工作顺序的混乱。您希望在每个输出中将最后一个带引号的重定向应用于其前面的重定向,以便原始标准输出文件描述符 (1) 的输出将转到 /dev/null,并且输出到标准错误文件描述符 (2) 将转到原始标准输出。
然而,这并不是 shell 重定向的工作原理。每次重定向都会导致文件描述符通过关闭“源”并将“目标”复制到其中来“重新映射”(请参阅man
页数dup(2)
and close(2)
), 为了。这意味着在您的命令中,标准输出首先替换为/dev/null
,然后将标准错误替换为标准输出,即/dev/null
已经。
什么有效:
因此,要获得所需的效果,只需反转重定向即可。然后你将有标准错误转到标准输出,而原始标准输出转到/dev/null
:
cmd 2>&1 >/dev/null | grep pattern
(请注意,1
before >
是不必要的 - 对于输出重定向,标准输出是默认的)
Addendum:查理提到重定向到&-
关闭文件描述符。如果使用支持该扩展的交互式 shell (bash
和其他一些实现,但不是全部,它是不标准 http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html),你也可以这样做:
cmd 2>&1 >&- | grep pattern
这可能会更好 - 它可以节省一些时间,因为当命令尝试写入标准输出时,调用write
可能会立即失败,而无需等待上下文切换到内核和驱动程序处理/dev/null
(取决于系统调用实现 - 有些人可能会在libc
功能,有些还可能有特殊处理/dev/null
)。如果有大量的输出是值得的,而且打字速度更快。
这在很大程度上会起作用,因为大多数程序并不关心它们是否无法写入标准输出(谁真正检查返回值)printf
?)并且不会介意标准输出被关闭。但有些程序可以通过失败代码来解决,如果write
失败 - 通常会阻止处理器、使用一些仔细的 I/O 库或记录到标准输出的程序。因此,如果它不起作用,请记住这是一个可能的原因并尝试/dev/null
.