【Linux】重定向

重定向

回顾计算机经典的冯诺依曼结构,计算机的组成包括运算器、控制器、存储器、输入设备和输出设备。常见的输入设备有键盘、鼠标、扫描仪等,常见的输出设备有显示器、蜂鸣器、打印机等;linux 系统通常以键盘为默认输入设备,称为标准输入设备,以显示器为默认输出设备,称为标准输出设备

重定向是指将原本应由标准输入设备输入的数据,改由其它文件或设备输入;原来应该输出到标准输出设备的数据,改为输出到其它文件或设备上。

文件标识符:linux 系统用 0~9 标识了与特定进程相关的数据流,系统启动一个进程的时候会同时为这个进程打开三个文件流:标准输入(stdin)、标准输出(stdout) 和标准错误输出(stderr),分别用文件标识符 0、1、2 来标识;如果要为进程打开其它的输入输出流,则需要从 3 开始标识。

I/O 重定向

I/O 重定向是重定向的一个重要部分,I/O 重定向可以将任何文件、命令、脚本、程序或执行结果重定向到另一个文件、命令、脚本或程序。I/O 重定向一共有下面五种

标准输出覆盖重定向 >

标准输出重定向可以将原本输出到标准输出设备的内容重定向到一个文件中或者其它输出设备中。如果目标文件不存在,则会先创建该文件;如果目标文件存在,则会覆盖其原来的内容。

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat ls_result
cat: ls_result: No such file or directory

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ ls -l > ls_result

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat ls_result
total 0
-rw-r--r-- 1 ljx0832 197121 0 八月 14 14:50 ls_result

这里使用 cat 命令查看 ls_result 的内容,发现文件不存在;然后将命令 ls -l 的结果重定向输出到文件 ls_result 中,会先创建文件,再把命令执行结果写进去;再使用 cat 命令查看文件内容,发现其内容就是命令 ls -l 的执行结果。

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ echo new text > ls_result

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat ls_result
new text

再将 echo 命令的执行结果重定向到文件 ls_result,然后查看其内容,发现原来的内容被覆盖了。

标准输出追加重定向 >>

标准输出追加重定向与标准输出覆盖重定向用法一样,不同的是一个是覆盖原来的内容,一个是在原来内容后面追加。

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ echo another text >> ls_result

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat ls_result
new text
another text

紧接着上面的例子,我们使用 echo 命令再重定向到文件中,然后查看文件内容,发现原来的内容还在,只是在后面追加新写入的内容。

标识输出重定向 >&

上面的例子使用 >>> 这两个重定向符号来进行重定向操作,其实标准的语法应该在重定向符号前面加上文件标识符,表示重定向到哪个输出流或者从哪个输入流重定向;当文体标识符为 1 时可以省略,所以下面的语句是等价的

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ echo hello world > file

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
hello world

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ echo hello world 1> file

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
hello world

同样的,对于标准输出追加重定向,标识符 1 也是可以省略的

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ echo "append text" >> file

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
hello world
append text

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ echo "append text too" 1>>file

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
hello world
append text
append text too

如果一个命令或一个脚本执行结果既有标准输出,也有标准错误输出,只使用重定向符号 > 或 >> 的话,只会把标准输出重定向到文件中,而标准错误输出则还是输出到标准输出设备,即显示器上。比如下面的这个脚本 test.sh

#!/bin/bash
# 正常执行
echo "normal command" > file
# 错误命令
error_command >> file

执行这个结果并查看文件 file 的内容

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ ./test.sh
./test.sh: line 5: error_command: command not found

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
normal command

可以看到标准输出内容被重定向到文件 file 中去了,而标准错误输出则没有重定向,直接在命令行打印出来了。如果要把标准错误输出也重定向,则必须要重定向符号前面加上文件标识符,标准错误输出的标识符是 2,修改脚本 test.sh

#!/bin/bash
# 正常执行
echo "normal command" > file
# 错误命令
error_command 2>> file

再次执行这个脚本

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ ./test.sh

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
normal command
./test.sh: line 5: error_command: command not found

可以看到标准输出和标准错误输出都被重定向到文件中去了。
额。这个例子好像并没有演示同时既有标准输出又有标准错误输出的情况,我们可以修改一下脚本,在脚本内不进行重定向,而是在执行脚本的时候进行重定向,修改脚本内容

#!/bin/bash
# 正常执行
echo "normal command"
# 错误命令
error_command

然后执行脚本的时候进行重定向

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ ./test.sh 1> file 2>> file

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
normal command
./test.sh: line 5: error_command: command not found

可以看到结果跟上面一样,标准输出和标准错误输出都被重定向到文件中去了。从这例子可以看到如果要对多个输出流进行重定向,在命令后面依次写上重定向符号和重定向目标即可,要注意的是只有标准输出流(即标识符为 1)才能省略文件标识符。

到目前为止,重定向输出的目标都是直接写文件名,其实重定向的目标也是可以用标识符来表示的,这就是 标识输出重定向。标识输出重定向的作用是将一个标识的输出重定向到另一个标识的输入,比如

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ ./test.sh 1> file 2>&1

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
normal command
./test.sh: line 5: error_command: command not found

2>&1 的意思是将标识符为 2 的输出流(即标准错误输出)作为标识符为 1 的输出流(即标准输出)的输入,也就是说将标准错误输出重定向到标准输出,而标准输出重定向到文件 file,所以最终标准错误输出也会重定向文件 file。再看下面的例子

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ ./test.sh 2>&1 1> file
./test.sh: line 5: error_command: command not found

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat file
normal command

这里调整了重定向的顺序,先使用 2>&1 将标准错误输出重定向到标准输出,而此时标准输出还没有进行重定向,紧接着 1> file 才将标准输出重定向到文件 file,所以标准输出被写入到文件 file 中,而标准错误输出直接打印到屏幕上了。

标准输入重定向 <

标准输入重定向将原本应由标准输入设备输入的内容转由文件内容输入,也就是将文件内容写入标准输入中。我们前面经常用 cat 命令来查看一个文件的内容,其实 cat 命令还有另外一个功能,就是接收一行输入,然后打印出来

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat
hello
hello
world
world

输入 cat 命令后 shell 会等待键盘输入,输入 hello 后回车,cat 命令接收标准输入内容并输出到标准输出,所以在屏幕上输出 hello;同样的输入 world 也会在屏幕上打印出来,按 ctrl+d 可以退出 cat 命令。如果要把标准输入改为从文件读取内容,则

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat hello.txt
hello
world

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat < hello.txt
hello
world

注意这两个 cat 命令的意义是不一样的,cat hello.txt 是查看文件 hello.txt 的内容,cat < hello.txt 是将 hello.txt 的内容重定向到 cat 命令的输入,然后进行输出。再比如,我们要使用 sort 命令对几个单词进行排序,可以像 cat 一样,输入 sort 命令之后,等待用户从标准输入设备输入几个单词,再按 ctrl+d 结束输入;也可以将单词保存在文件中,再从文件重定向到输入

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat fruit.txt
banana
apple
pear

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ sort < fruit.sh
apple
banana
pear

管道

管道可以将一个命令的执行结果作为下一个命令的输入,使用管道连接符 | 来连接进程,由管道连接起来的进程会自动按顺序运行,如同有一个数据流一样。使用管道也可以实现重定向,比如上面的 sort,可以使用管道来重定向输入

ljx0832@ljx0832-PC MINGW64 /d/learn/shell/redirect
$ cat fruit.txt | sort
apple
banana
pear

这个管道会先执行 cat 命令,然后把 cat 命令执行的结果作为 sort 命令的输入,相当于 sort 命令的输入由将标准输入重定向到 cat 命令的输出。

猜你喜欢

转载自blog.csdn.net/xingxinmanong/article/details/77163352