例子
对于不理解的同学,可以先直接运行一个demo,看看具体有什么区别,我们从结果来进行分析。
#include<stdio.h>
#include<fcntl.h>
int main()
{
printf("nihao \n");
perror("cuowu");
return 0;
}
之后进行编译,再测试:
从结果我们可以看出,a.out > outfile 2>&1 将标准输出和错误输出都重定向到了outfile文件中;a.out 2>&1 > outfile将错误输出输出到终端,标准输出到outfile中。(细心的同学可能对第一个输出的顺序感到奇怪,有兴趣的可以了解一下延迟写的概念)
分析
首先我们需要了解到linux中如何将文件描述符和磁盘上的文件进行关联的。
在进程中,会将每一个文件描述符进行记录,将对应的文件描述符指向一个文件表项。该文件表项保存的是文件的状态标志(只读,只写,可读可写)和偏移量等信息,V节点指针指向一个V节点表项。你可以认为这个V节点表项就是我们磁盘上的具体文件了。
因此你要知道linux中文件描述符和文件表项,V节点表项相关联的。
shell为我们做了那些事情?
我们知道进程中的文件描述符0,1,2。一般都是标准输入和标准输出,错误输出的接口。这些其实都是shell为我们做的配置。它将这三个文件描述符都指向了终端文件表项。才会出现我们的标准输入,标准输出,错误输出都是从终端获取和输出。
a.out > outfile 做了哪些事?
我们知道 该语句的效果就是将 a.out 标准输出重定向到 outfile中。但是从代码上做了哪些操作呢?将标准输出文件描述符改1指向outfile的文件表项。而outfile的文件表项中的V节点肯定指向磁盘中的outfile文件。所以最终会输出到outfile文件中。
fd1>&fd2 是什么意思?
linux中表示将fd1的文件指针指向fd2的文件指针指向的文件表项。
了解以上的知识点以及shell是从左往右进行解析,大概就知道a.out > outfile 2>&1和 a.out 2>&1 > outfile的区别了。
a.out > outfile 2>&1
a.out > outfile ,表示将 文件描述符1指向outfile的文件表项。 2>&1 ,表示将文件描述符2指向文件描述符1指向文件表项(此时,文件描述符1指向outfile文件表项)。因此a.out 的错误输出和标准输出都会输出到outfile文件中。
a.out 2>&1 > outfile
a.out > 2>&1 ,表示将文件描述符2指向文件描述符1指向的文件表项(此时,文件描述符符1指向终端的文件表项)。 > outfile ,表述将文件描述符1指向outfile的文件表项。因此,标准输出会输出到outfile中。错误输出会输出到终端