You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu 22.04.2 LTS下Shell重定向与管道命令的行为疑问

Ubuntu 22.04.2 LTS下Shell重定向与管道命令的行为疑问

嗨,我来帮你理清这两个命令的行为差异——核心问题在于shell处理重定向的顺序和|&这个语法的实际作用,咱们一步步拆解:

首先明确bash里|&的本质:它等价于2>&1 |,也就是把前一个命令的标准错误(stderr,文件描述符2)重定向到标准输出(stdout,文件描述符1),再把stdout的内容通过管道传给后面的命令。而且shell处理重定向是从左到右依次执行的,后面的重定向会覆盖前面的配置,这是关键!


第一个疑问:ls a* z* 2> /dev/null |& cat 为什么错误没被丢弃?

你原本以为2> /dev/null会把错误扔进/dev/null,但实际shell的执行顺序是这样的:

  1. 先创建管道,把ls的stdout(fd1)连接到管道的写入端;
  2. 执行2> /dev/null:此时ls的stderr(fd2)被指向/dev/null;
  3. 执行|&隐含的2>&1:把ls的stderr(fd2)重新指向当前fd1的位置——也就是管道的写入端(因为之前管道已经把fd1连到管道了)。

相当于你先把错误导向垃圾桶,然后又把垃圾桶的出口改接到了管道,所以ls找不到z*的错误信息最终还是通过管道传给了cat,被打印出来了。


第二个疑问:ls a* z* 1> /dev/null |& cat 为什么没有输出?

同样用执行顺序来分析:

  1. 先创建管道,把ls的stdout(fd1)连接到管道的写入端;
  2. 执行1> /dev/null:把ls的stdout(fd1)重定向到/dev/null;
  3. 执行|&隐含的2>&1:把ls的stderr(fd2)重定向到当前fd1的位置——也就是/dev/null。

这时候ls的正常输出(a1.txt、a2.txt)被扔进/dev/null,找不到z*的错误信息也被跟着扔进/dev/null了,管道里没有任何内容传给cat,自然就没有输出。

如果你想只丢弃正常输出、显示错误信息,正确的写法可以是:

ls a* z* 1> /dev/null

或者非要用管道的话(虽然没必要),可以这样写:

ls a* z* 2>&1 1> /dev/null | cat

这里先把stderr重定向到原stdout(终端),再把stdout扔进/dev/null,错误信息就会保留下来。


备注:内容来源于stack exchange,提问作者tahzibi.jafar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 09:54:50