输入输出重定向
输入重定向指的是将原来从标准输入读取数据的位置重新定向为从其他位置读取数据,输出重定向指的是把原来要输出到标准输出的内容,重新定向输出到指定的其他位置。
输入输出重定向通常与文件描述符 FD 有关,shell 的 FD 通常为10个,即 0~9,最常用的有 3 个,即 0(stdin)、1(stdout)、2(stderr)。
重定向操作符
命令从键盘的输入读入数据是很常见的的。
1 | [user1@study ~]$ read -p 'Input something: ' line ; echo "Your input : ${line}" |
用 <
来改变读进的数据位置(stdin),使之从指定的位置读进。0 是 <
的默认值,因此 <
与 0<
是一样的。
1 | [user1@study ~]$ read -p 'Input something: ' line < file |
用 >
来改变送出位置,使之输出到指定的位置。1 是 >
的默认值,因此 >
与 1>
是一样的。如果指定的文件不存在则自动创建这个文件并以覆盖方式写入数据,如果文件存在将会把命令的输出覆盖掉文件内容。所以 >
也叫覆盖重定向。
1 | [user1@study ~]$ date +"Today: %F %T" |
用 >>
来改变送出位置,使之输出到指定的位置。1 是 >>
的默认值,因此 >>
与 1>>
是一样的。如果指定的文件不存在则自动创建这个文件并以追加的方式写入数据,如果文件存在将会把命令的输出追加到文件中。所以 >>
也叫追加重定向。
1 | [user1@study ~]$ cat file.txt |
如果想要对标准错误输出进行重定向,需要使用其文件描述符 2
配合重定向操作符 >
和 >>
来使用,即 2>
和 2>>
。这在记录日志或者在调试的时候显得十分有用。
1 | [user1@study ~]$ ls abc 2> log1.txt |
但是要注意文件描述符和重定向操作符必须紧挨着,不能有空格,否则将无法完成重定向。
1 | [user1@study ~]$ cat bcd 2 >> log1.txt |
用 2>&1
将会把标准错误输出重定向到标准输出。
1 | [user1@study ~]$ head 123.txt >> log1.txt 2>&1 |
你可以理解为不管是正确输出还是错误输出,都并到一个数据流来处理。
1 | [user1@study ~]$ echo '123' > 123.txt |
用 &>
将会把标准错误输出已覆盖的方式重定向一个文件或设备,用起来基本上和 command > filename 2>&1
效果是一样的
1 | [user1@study ~]$ cat log1.txt |
重定向时还可以对标准输出和标准错误输出分别指定各自的输出位置。
1 | [user1@study ~]$ eco 'yes' > info.log 2> err.log |
在输入输出重定向中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进数据。因此不管命令输出是错误还是正确,在覆盖重定时文件时都会先被清空。
1 | [user1@study ~]$ cat file |
/dev/null
/dev/null
称为空设备,是一个特殊的设备文件,它会丢弃一切写入其中的数据。/dev/null
常被程序员称为位桶(bit bucket)或者黑洞(black hole)。空设备通常被用于丢弃不需要的输出流,或作为用于输入流的空文件。当你读它的时候,它会提供无限的空字符。
1 | [user1@study ~]$ ls *.txt &> /dev/null |
在很多时候我们并期望看到命令的输出,只关心执行正确与否。此时可以做输出重定向,并且重定向到 /dev/null
即可
1 | [user1@study ~]$ echo $(date) | grep 2015 &>/dev/null |
写在后面
有时候需要清空文件的内容而不是删除文件本身。
1 | [user1@study ~]$ cat test.log |
这个功能看似没什么复杂的,但在实际工作过程中经常会因为粗心在追加重定向时漏写了一个 >
,直接将文件覆盖了, 结果酿成了悲剧。
如何才能禁止覆盖一个已经存在的文件呢?Linux 中有一个内置的 shell 命令 set
,结合它的选项 -C
就能实现这个功能。
1 | [user1@study ~]$ set -C |
如果百分之百确定要覆盖,可以使用 set +C
关闭这个功能等到操作完成之后再开启。
1 | [user1@study ~]$ set +C |
或者使用 >|
在重定向时强进行制覆盖
1 | [user1@study ~]$ set -C |
实际上 set -o noclobber
等同于 set -C
,set +o noclobber
等同于 set +C
1 | [user1@study ~]$ set -o noclobber |