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的执行顺序是这样的:
- 先创建管道,把
ls的stdout(fd1)连接到管道的写入端; - 执行
2> /dev/null:此时ls的stderr(fd2)被指向/dev/null; - 执行
|&隐含的2>&1:把ls的stderr(fd2)重新指向当前fd1的位置——也就是管道的写入端(因为之前管道已经把fd1连到管道了)。
相当于你先把错误导向垃圾桶,然后又把垃圾桶的出口改接到了管道,所以ls找不到z*的错误信息最终还是通过管道传给了cat,被打印出来了。
第二个疑问:ls a* z* 1> /dev/null |& cat 为什么没有输出?
同样用执行顺序来分析:
- 先创建管道,把
ls的stdout(fd1)连接到管道的写入端; - 执行
1> /dev/null:把ls的stdout(fd1)重定向到/dev/null; - 执行
|&隐含的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
相关产品推荐
相关产品推荐

