1、概念
在解释什么是重定向之前,先来说说什么是文件描述符
Linux 文件描述符
文件描述符可以理解为 Linux 系统为文件分配的一个数字,范围是 0-3 ,用户也可以自定义文件描述符,但是自定文件描述符不在这里的讨论范围
文件描述符(file descriptor)
| 名称 | 类型 | 文件描述符 | 操作 |
|---|---|---|---|
| 标准输入 | standard input | 0 | <,<< |
| 标准输出 | standard output | 1 | >,>> |
| 标准错误输出 | standard error output | 2 | 2>,2>> |
文件描述符的存储位置位于 /proc/self/fd ,文件描述符是通过一系列软链接指向的默认输出设备,这里我们的默认设备就是模拟终端
模拟终端的文件可以使用命令 tty 来查看
1 | [divent@bash]$ ls -al /proc/self/fd |
对于一条 Linux 的命令执行的过程如下1
2
3
4
5
6
7
8
9
10
11start=>start: File
stain=>subroutine: Standard Input
command=>condition: Command
op1=>operation: Standard Output
op2=>operation: Standard Error
end1=>end: File
end2=>end: File
start->stain(right)->command
command(yes)->op1->end1
command(no)->op2->end2
- 用户开始从键盘(键盘在 Linux 上属于文件)输入数据,也就是系统从文件中读取数据的时候
- shell 将接受到的数据(标准输入)传递给相应的命令开始执行
- (yes)执行成功后,即可获得标准正确输出。(no)执行失败后,获得标准错误输出
- 在默认情况下,标准正确输出的结果与标准错误输出的缺省输出都为当前用户执行的终端
一个命令执行以前,会准备好所有的输入输出,默认分别绑定 stdin(0),stdout(1),stderr(2)。如果在准备命令的时候出现错误,那么这个命令将不会执行
2、输出重定向
格式
1 | command [OPTION]{>,>>} [File] |
>为覆盖输出,>>为追加输出
示例
1 | # 假设当前文件夹有文件 test2 |
这里可以看到同时拥有的标准输出与标准错误输出都显示在了屏幕上
现在我们要将输出写入到文件中
1 | # 假设已经有文件 test2 , test3 |
因为这里的文件只默认接受了标准输出,所以标准错误输出就输出到了终端上
我们也可以将标准错误输出写入到文件1
2
3
4
5# 假设已经有文件 test2 , stderr
[divent@bash]$ ls test test2 2> stderr
test2
[divent@bash]$ cat stderr
ls: cannot access test: No such file or directory
这里获得的结果就和刚刚的结果正好相反
我们也可以将标准输出与标准错误输出都重定向到不同的文件1
2
3
4
5
6# 假设已经有文件 test2 , stdout , stderr
[divent@bash]$ ls test test2 1> stdout 2>stderr
[divent@bash]$ cat stdout
test2
[divent@bash]$ cat stderr
ls: cannot access test: No such file or directory
这里我们就将两个不同的输出输出到了指定的文件中
我们也可以将两个输出同时输出到同一个文件中1
2
3
4
5# 假设已经有文件 test2 , test3
[divent@bash]$ ls test test2 &> test3
[divent@bash]$ cat test3
ls: cannot access test: No such file or directory
test2
这里就使用 \& 将两种输出同时输出到了同一个文件
我们也可以只接受某一种输出,而将其他的输出导向到其他地方1
2
3
4
5
6# 假设已经有文件 test2
[divent@bash]$ ls test test2 2>&-
test2
[divent@bash]$ ls test test2 2>/dev/null
test2
# &- 意义为关闭这个输出,/dev/null 是 linux 的黑洞设备
注意
- shell遇到
>操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空。 >>操作符,判断右边文件是否存在,如果不存在,先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1]然后,与左边对应的输出绑定。- 一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行
3、输入重定向
格式
1 | command {<} [File] {<<} [Word] |
这里的
<与<<意义不是类似于输出重定向的操作符,<是从文件中取出数据到指定的文件中
示例
1 | [divent@bash]$ cat > newfile |
cat 命令直接使用的话可以直接接收键盘的输入
现在来尝试从文件中输入1
2
3
4
5
6
7
8# 这里的示例我们使用刚才创建的 test3 文件
[divent@bash]$ cat test3
ls: cannot access test: No such file or directory
test2
[divent@bash]$ cat > newfile < test3
[divent@bash]$ cat newfile
ls: cannot access test: No such file or directory
test2
这里的先将文件中的数据提取到了命令 cat 中 ,然后由 cat 写入到 newfile 中
4、自定义输入输出设备
解释
除了使用系统给你定义的文件描述符以外,用户还可以自己自定义文件描述符,首先使用 ulimit -n 来查看文件描述符的上限,然后使用命令 exec 来为一个文件添加文件描述符
示例
1 | # 首先查看一下现在已经被占用的文件描述符 |
最后说两句
- 如果不是很好理解的话,一定要贯彻 Linux 一切皆文件的理念,文件描述符最终也是指向的是文件
- 使用自己自定义的描述符可以简化一些备份之类的任务
- 在 shell 脚本中,输入输出重定向是经常使用的