使用文件描述符重定向 - 具体示例

使用文件描述符重定向 - 具体示例

我在读本文档其中给出了以下有关重定向和文件描述符的示例。

ls > dirlist 2>&1

将把标准输出和标准错误定向到文件目录列表,而命令

ls 2>&1 > dirlist

只会将标准输出定向到 dirlist。这对于程序员来说是一个有用的选项。

这些例子是不是都是错误的?在我看来第二例如“将标准输出和标准错误定向到文件目录列表”,而第一的例如“仅将标准输出定向到目录列表”。

如果我错了(......可能......)有人可以清楚地解释这两个例子的逻辑吗?

答案1

首先,您需要了解n>&m语法。这是一个复制操作,意味着将 m 复制到 n。查看部分“3.6.8 复制文件描述符”

我在看这篇文章的时候也有和你一样的疑问。所以我可以尝试向你解释一下:

ls > dirlist 2>&1 

使用上面的命令,首先将输出重定向到 dirlist by > dirlist2>&1表示将文件描述符1复制到2,换句话说,使fd2成为fd1的副本。现在fd1已经指向dirlist,使fd2成为fd1的副本意味着fd2也指向dirlist。结果是fd1->dirlist,fd2->dirlist。

ls 2>&1 > dirlist   

这样,您首先将 fd2 制作为 fd1 的副本,而 fd1 仍然是终端,因此 fd2->terminal。然后将 fd1 重定向到 dirlist。结果是,fd2 -> 终端,fd1->dirlist。

答案2

方向是从左到右处理的。

ls > dirlist 2>&1

使 shell 最终将自身变成 ls,执行以下系统调用(为简洁起见,省略错误检查)。

/* Handle > dirlist */
int temp_fd = open("dirlist",O_WR);  /* Open dirlist for output */
dup2(temp_fd, 1); /* Make file descriptor 1 (stdout) point to dirlist */
close(temp_fd);  /* Don't need this other file descriptor for dirlist */
/* Handle 2>&1 */
dup2(1,2); /* Make fd 2 be a copy of fd 1, which points to dirlist */

所以首先改变fd 1,然后改变fd 2。

相反 ls 2>&1 > dirlist 会

/* Handle 2>&1 */
dup2(1,2); /* Make fd 2 be a copy of fd 1, the original stdout */
/* Handle > dirlist */
int temp_fd = open("dirlist",O_WR);  /* Open dirlist for output */
dup2(temp_fd, 1); /* Make file descriptor 1 (stdout) point to dirlist */
close(temp_fd);  /* Don't need this other file descriptor for dirlist */

另一种看待它的方式就是将其视为作业。本来fd1=initial_stdout,那么

/* ls > dirlist 2>&1 */
fd1=to_dirlist
fd2=fd1 (i.e. to_dirlist)

/* ls 2>&1 > dirlist */
fd2=fd1 (i.e. initial_stdout)
fd1=to_dirlist.

或者你可以说copy by value而不是copy by reference

相关内容