man bash
在重定向时这样说:
注意重定向的顺序很重要。例如命令
ls > dirlist 2>&1
将标准输出和标准错误都指向文件目录列表,而命令
ls 2>&1 > dirlist
仅将标准输出定向到文件目录列表,因为标准在标准输出被重定向到目录列表。
我真的不明白这个部分:
在将标准输出重定向到目录列表之前,标准错误已从标准输出中复制。
从我的角度来看,>
只是指重定向,就像ls > dirlist
将ls
的输出重定向到文件dirlist
一样。
因此,2>&1
应该将stderr重定向到stdout,然后将stdout重定向到dirlist
(> dirlist
(。然而,显然只有stdout被重定向到dirlist
。
这是怎么回事;从流B复制的流A";?
Shell重定向实际上只是调用系统调用dup2()
。引用自https://man7.org/linux/man-pages/man2/dup.2.html--
int dup2(int oldfd, int newfd);
dup((系统调用分配一个新的文件描述符,该描述符引用与描述符oldfd相同的打开文件描述。
这实际上并没有像";重定向流"——相反,它改变了打开文件的表,使表中某个位置的文件句柄从表中的另一个位置指向。
所以,让我们看看您的第一个例子,ls > dirlist 2>&1
- 使用
open(2)
打开文件dirlist
dup2()
用于将open()
创建的文件句柄复制到FD 1(>
的默认值(,并关闭动态创建的句柄- CCD_ 18用于将FD 1复制到FD 2
。。。净结果:FD 1和FD 2都指向CCD_ 19。
现在,让我们看看您的下一个示例,ls 2>&1 >dirlist
dup2()
用于将先前在FD 1打开的内容复制到FD 2open()
用于打开文件dirlist
dup2()
用于将目录列表上的句柄复制到FD 1,并关闭动态创建的句柄
。。。净结果:FD 2现在指向FD 1的先前值,而FD 1现在指向dirlist
。
您的手册与GNU网站上的手册有点不同,但请参阅Duplicateing File Descriptors:
重定向运算符[n]<amp;word用于复制输入文件描述符。如果单词扩展到一个或多个数字,则由n表示的文件描述符将成为该文件描述符的副本。。。运算符[n]>amp;word类似地用于复制输出文件描述符。
因此,当您编写2>&1
时,您表示希望文件描述符2成为文件描述符1的副本。它并没有真正连接到文件描述符1,它只是指向同一个地方。由于它只是一个副本,对文件描述符1的更改不会自动应用回文件描述符2。这就是为什么秩序很重要。