在《鸟哥的Linux私房菜》第三版的329-330,鸟哥介绍了数据流的重定向,里面提到一点,如何你想把正确与错误数据都写到一个文件中,这个时候用下面第一行代码是错误的,而使用第二行和第三行代码才是正确的
find /home -name .bashrc > list 2>list
find /home -name .bashrc > list 2>&1
find /home -name .bashrc &> list
至于第一行错误的原因,鸟哥说这是因为两条数据同时写入一个文件,有没有使用特殊的语法,此时两条数据可能会交叉写入该文件内,造成次序的错乱。
在刚开始学Linux的时候,我只记住了结论,就是用&>
将标准输出和标准错误输出写入到一个文件中,而2>&1
要记忆4个字符,还得记住要放在文件的后面,脑容量不够,就没有记住。而这两天读到了《Linux命令行与shell脚本编程大全》第3版第15章的时候,我终于明白了为什么第一行代码会出现次序错乱,2>&1
为什么这些写是正确的。
首先,你需要理解1>
和2>
里的数字1和2指的是文件描述符(file descriptor)。 所谓的文件描述符是一个非负整数,用于标识打开的文件。在bash shell中,1表示STDOUT(标准输出),2表示STDERR(标准错误), 当然还有一个0表示的STDIN(标准输入)。我们还可以定义其他整数,但这个就比较复杂,算是高级技巧了。
其次,你要知道">"和另一个符号"<"是两个常用重定向符号。所谓的重定向,就是改变数据流的原本走向,本来输出到屏幕的输出写入到文件中,本来需要从文件读取的数据,可以从键盘上输入
那么&
符号是什么含义呢?在C语言里&
是一个求址符号,因此&1
你可以理解成获取标准输出对象的地址,而>&1
就表示把输入定向到了标准输出, >&2
也就是把输出定向到了标准错误输出。那么我们就可以在脚本里面写一些标准错误输出了, 比如创建一个脚本, test.sh
#!/bin/bash
echo "This is a first normal output"
echo "This is a first error" >&2
echo "This is a second error" >&2
echo "This is a second nromal output"
以bash test.sh 1> a 2>a
运行的话,由于同时对a文件进行写入操作,不同的磁盘写入速度,会有不同的结果,因为前面的输出很可能会后面的覆盖了。
cat a
This is a first error
This is This is a second nromal output
从我的输出结果可以推测出,首先是输出“This is a first normal output”,但是被后来者“This is a first error”给覆盖了。然后“This is a second error"写到一半,就被“This is a second nromal output”给覆盖了。
而以bash test.sh 1> a 2>&1
的话,就会把标准错误输出定向到标准输入上,就会以此输出了。
This is a first normal output
This is a first error
This is a second error
This is a second nromal output
考虑到这个操作比较常用,每次都要写2>&1
太麻烦了,于是就定义了一个&>
符号方便使用。