我读到重定向是从左到右处理的。所以在这个例子中
command 2>&1 | less
有人会认为 fd 2 首先被定向到 fd 1,然后 fd 1 被发送到管道。所以 fd 1 和 2 指向不同的地方。
但实际上这里的 fd 1 和 2 都指向管道,因为由于某种原因,fd 1 首先发送到管道,然后 fd 2 发送到 fd 1。为什么在这种情况下从右到左处理重定向?
管道不是重定向,因此实际上重定向(您的示例中只有一个)正在按照您的想法进行处理。 管道最后是一个单独的东西。
原因是管道与重定向不同。重定向影响一个命令,而管道连接两个命令。
fd 2 指向 fd 1 所指向的位置(即 stdout)。在
command 2>&1 | less
在重定向生效之前,stdout 已经指向管道!
更详细的解释请参见:
http://www.linuxtutorialblog.com/post/tutorial-the-best-tips-tricks-for-bash
# ...
# Well, here's a thing you should remember: bash reads command statements from
# the left to the right, but, before that, determines if there are multiple command
# statements and in which way they are separated. Therefore, bash already read
# and applied the "|" pipe symbol and stdout is already pointing to the pipe.
# ...
这是因为管道首先“发生”。
command 2>&1 | less
$ strace -qf -e 'dup3,pipe2' sh -c 'ls -al file-exist file-doesnt-exist 2>&1 | grep f'
pipe2([3, 4], 0) = 0 # Parent create 2 fds, fd4 for |
[pid 317043] dup3(3, 0, 0) = 0 # 2nd process changes stdin to fd3
[pid 317042] dup3(4, 1, 0) = 1 # 1st process changes stdin to fd3
[pid 317042] dup3(1, 2, 0) = 2 # 1st process redirects stderr (fd2) to stdout (fd1)