1、重定向输入和输出
有些时候你想要保存某个命令的输出而不仅仅只是让它显示在显示器上。bash shell提供了几个操作符,可以将命令的输出重定向到另一个位置(比如文件)。重定向可以用于输入,也可以用于输出,可以将文件重定向到命令输入
1.1 输出重定向
最基本的重定向将命令的输出发送到一个文件中。bash shell用大于号(>)来完成这项功能:
1 command > outputfile
之前显示器上出现的命令输出会被保存到指定的输出文件中。
1 $ date > test6
2 $ ls -l test6
3 -rw-r--r-- 1 user user 29 Feb 10 17:56 test6
4 $ cat test6
5 Thu Feb 10 17:56:58 EDT 2014
6 $
重定向操作符创建了一个文件test6(通过默认的umask设置),并将date命令的输出重定向到该文件中。如果输出文件已经存在了,重定向操作符会用新的文件数据覆盖已有文件。
1 $ who > test6
2 $ cat test6
3 user pts/0 Feb 10 17:55
4 $
现在test6文件的内容就是who命令的输出。
有时,你可能并不想覆盖文件原有内容,而是想要将命令的输出追加到已有文件中,比如你正在创建一个记录系统上某个操作的日志文件。在这种情况下,可以用双大于号(>>)来追加数据。
1 $ date >> test6
2 $ cat test6
3 user pts/0 Feb 10 17:55
4 Thu Feb 10 18:02:14 EDT 2014
5 $
test6文件仍然包含早些时候who命令的数据,现在又加上了来自date命令的输出。
1.2 输入重定向
输入重定向和输出重定向正好相反。输入重定向将文件的内容重定向到命令,而非将命令的输出重定向到文件。
输入重定向符号是小于号(<):
1 command < inputfile
一个简单的记忆方法就是:在命令行上,命令总是在左侧,而重定向符号“指向”数据流动的方向。小于号说明数据正在从输入文件流向命令。
这里有个和wc命令一起使用输入重定向的例子。
1 $ wc < test6
2 2 11 60
3 $
wc命令可以对对数据中的文本进行计数。默认情况下,它会输出3个值:
- 文本的行数
- 文本的词数
- 文本的字节数
通过将文本文件重定向到wc命令,你立刻就可以得到文件中的行、词和字节的计数。这个例子说明test6文件有2行、11个单词以及60字节。
还有另外一种输入重定向的方法,称为内联输入重定向(inline input redirection)。这种方法无需使用文件进行重定向,只需要在命令行中指定用于输入重定向的数据就可以了。乍看一眼,这可能有点奇怪,但有些应用会用到这种方式。
内联输入重定向符号是远小于号(<<)。除了这个符号,你必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致。
1 command << marker
2 data
3 marker
在命令行上使用内联输入重定向时,shell会用PS2环境变量中定义的次提示符来提示输入数据。下面是它的使用情况。
1 $ wc << EOF
2 > test string 1
3 > test string 2
4 > test string 3
5 > EOF
6 3 9 42
7 $
次提示符会持续提示,以获取更多的输入数据,直到你输入了作为文本标记的那个字符串。wc命令会对内联输入重定向提供的数据进行行、词和字节计数。
linux文件描述符:可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作。 用户可以自定义文件描述符范围是:3-num,这个最大数字,跟用户的:ulimit –n 定义数字有关系,不能超过最大值。
linux启动后,会默认打开3个文件描述符,分别是:标准输入standard input 0,正确输出standard output 1,错误输出:error output 2
以后打开文件后。新增文件绑定描述符 可以依次增加。 一条shell命令执行,都会继承父进程的文件描述符。因此,所有运行的shell命令,都会有默认3个文件描述符。
对于任何一条linux 命令执行,它会是这样一个过程:
一个命令执行了:
先有一个输入:输入可以从键盘,也可以从文件得到
命令执行完成:成功了,会把成功结果输出到屏幕:standard output默认是屏幕
命令执行有错误:会把错误也输出到屏幕上面:standard error默认也是指的屏幕
文件输入输出由追踪为一个给定的进程所有打开文件的整数句柄来完成。这些数字值就是文件描述符。最为人们所知的文件米描述符是 stdin, stdout 和 stderr,文件描述符的数字分别是0,1和2。这些数字和各自的设备是保留的。一个命令执行前,先会准备好所有输入输出,默认分别绑定(stdin,stdout,stderr),如果这个时候出现错误,命令将终止,不会执行。命令解析过程,可以参考:Linux Shell 通配符、元字符、转义符使用实例介绍
这些默认的输出,输入都是linux系统内定的,我们在使用过程中,有时候并不希望执行结果输出到屏幕。我想输出到文件或其它设备。这个时候我们就需要进行输出重定向了。
linux shell下常用输入输出操作符是:
1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ; /dev/stdin -> /proc/self/fd/0 0代表:/dev/stdin
2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ; /dev/stdout -> /proc/self/fd/1 1代表:/dev/stdout
3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ; /dev/stderr -> /proc/self/fd/2 2代表:/dev/stderr
输出重定向:
格式:
command-line1 [1-n] > file或文件操作符或设备
上面命令意思是:将一条命令执行结果(标准输出,或者错误输出,本来都要打印到屏幕上面的) 重定向其它输出设备(文件,打开文件操作符,或打印机等等)1,2分别是标准输出,错误输出。
1 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls
2 #找了个空的目录创建 test.sh 文件
3 zhengchuanyu@zhengchuanyu:~/xiaoyu$ touch test.sh
4 #显示当前目录文件 test.sh test1.sh, test1 实际不存在
5 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh
6 ls: cannot access 'test1.sh': No such file or directory
7 test.sh
8
9 #标准输出与错误输出都显示在屏幕上了,现在需要把正确输出写入zcy.txt
10 #1>中的1可以省略不写,默认标准输出
11 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 1>zcy.txt
12 ls: cannot access 'test1.sh': No such file or directory
13 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat zcy.txt
14 test.sh
15
16 #把错误输出不输出到屏幕,输出到err.txt
17 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 1>zcy.txt 2>err.txt
18 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat zcy.txt err.txt
19 test.sh
20 ls: cannot access 'test1.sh': No such file or directory
21 #继续追加把输出写入zcy.txt err.txt ">>" 追加操作符
22 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 1>>zcy.txt 2>>err.txt
23 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat zcy.txt err.txt
24 test.sh
25 test.sh
26 ls: cannot access 'test1.sh': No such file or directory
27 ls: cannot access 'test1.sh': No such file or directory
28
29 #将错误输出信息关闭掉
30 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 2>&-
31 test.sh
32 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 2>/dev/null
33 test.sh
34 #&[n] 代表是已经存在的文件描述符,&1 代表标准输出,&2 代表错误输出,&- 代表关闭与他绑定的描述符
35 #/dev/null 是Linux中的黑洞设备,什么信息只要输出给这个设备,都会被吞掉
36
37 #关闭所有输出
38 #关闭 1,2文件描述符
39 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 1>&- 2>&-
40 #将1,2输出转发给/dev/null 设备
41 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh 1>/dev/null 2>/dev/null
42 #将标准错误输出 2 绑定 标准输出 1,然后将标准输出发送给 /dev/null设备,这种常用
43 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh >/dev/null 2>&1
44 #& 代表标准输出、标准错误输出,将所有标准输出、标准错误输出输入到/dev/null 设备
45 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls test.sh test1.sh &>/dev/null
46 zhengchuanyu@zhengchuanyu:~/xiaoyu$
注意:
1、shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空。
2、“>>”操作符,判断右边文件,如果不存在,先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1,2]然后,与左边的标准输出(1)或错误输出(2) 绑定。
3、当命令:执行完,绑定文件的描述符也自动失效。0,1,2又会空闲。
4、一条命令启动,命令的输入,正确输出,错误输出,默认分别绑定0,1,2文件描述符。
5、一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行
输入重定向
格式:
command-line [n] <file或文件描述符&设备
将然有,命令默认从键盘获得的输入,改成从文件,或者其它打开文件以及设备输入。执行这个命令,将标准输入0,与文件或设备绑定。将由它进行输入。
实例:
1 #先创建一个fd.txt,待会会用到它,从fs.txt中标准输入
2 zhengchuanyu@zhengchuanyu:~/xiaoyu$ touch fd.txt
3 #从【键盘】中获取标准输入 获得数据,然后标准输出给 file 文件
4 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat > file
5 string1
6 string2
7 string3
8 #这里按下 ctrl + d离开
9
10 #从fd.txt 中获得标准输入数据,然后标准输出给file文件
11 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat > file < fd.txt
12
13
14 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat > file << EOF
15 > string4
16 > string5
17 > string6
18 > EOF
19 # << 这个远小于符号,它代表的是“结束的输入字符”的意思,这样当空行输入 EOF 字符,输入自动结束,不用 ctrl + d
20 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat file
21 string4
22 string5
23 string6
24 zhengchuanyu@zhengchuanyu:~/xiaoyu$
exec绑定重定向
格式:
exec 文件描述符[n] <或> file或文件描述符或设备
在上面讲的输入,输出重定向 将输入,输出绑定文件或设备后。只对当前那条指令是有效的。如果需要在绑定之后,接下来的所有命令都支持的话。就需要用exec命令
实例:
1 #将fd 6 与标准输出绑定
2 zhengchuanyu@zhengchuanyu:~/xiaoyu$ exec 6>&1
3 #查看文件描述符,出现了6
4 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls /proc/self/fd
5 0 1 2 3 6
6 #将接下来所有命令的标准输出绑定到zcy.txt中(输出到)zcy.txt)
7 zhengchuanyu@zhengchuanyu:~/xiaoyu$ exec 1>zcy.txt
8 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls -al
9 #执行命令,发现什么都没有,因为标准输出已经输出到zcy.txt中了,但是此时如果cat zcy.txt,你会发现你依旧看不到任何内容,不要忘了上面做的事情,嘿嘿
10
11 #将标准输出绑定 fd 6
12 zhengchuanyu@zhengchuanyu:~/xiaoyu$ exec 1>&6
13 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls /proc/self/fd
14 0 1 2 3 6
15 #关闭fd 6描述符
16 zhengchuanyu@zhengchuanyu:~/xiaoyu$ exec 6>&-
17 zhengchuanyu@zhengchuanyu:~/xiaoyu$ ls /proc/self/fd
18 0 1 2 3
19
20 #在看看敲入命令,发现恢复了
21 zhengchuanyu@zhengchuanyu:~/xiaoyu$ cat zcy.txt
22 total 8
23 drwxrwxr-x 2 zhengchuanyu zhengchuanyu 4096 6月 11 00:56 .
24 drwxr-xr-x 29 zhengchuanyu zhengchuanyu 4096 6月 11 00:55 ..
25 -rw-rw-r-- 1 zhengchuanyu zhengchuanyu 0 6月 11 00:56 zcy.txt
26 zhengchuanyu@zhengchuanyu:~/xiaoyu$