这一篇讲一下重定向shell
有些时候你想要保存某些命令产生的输出而不是在显示器上显示它。
为了应对这样的问题 bash shell 也就提供了一些重定向的操做符。
咱们先了解一些基本的应用。bash
输出重定向
输出重定向最基本的就是将命令的输出重定向到文件中,bash shell 采用了( > ) 这个符号来实现这个功能。
command > outputfile
这样本应该在显示器上显示的内容就保存在了文件中。
命令行#!/bin/bash
today=`date +%y%m%d`
echo $today
ls -al > log.$today
$ ./shell5
171108
$
$ cat log.171108
-rw-rw-r--. 1 forever forever 0 11月 8 19:44 log.171108
-rwxrw-r--. 1 forever forever 84 11月 8 17:21 shell1
-rwxrw-r--. 1 forever forever 45 11月 8 18:25 shell2
-rwxrw-r--. 1 forever forever 187 11月 8 18:42 shell3
-rwxrw-r--. 1 forever forever 50 11月 8 18:52 shell4
-rwxrw-r--. 1 forever forever 66 11月 8 19:44 shell5
......
$
这样就将命令的输出重定向到了log.$today中,log.$today这也是日志文件获取时间的一种方式。
( > )使用的时候就会将原有文件覆盖。可是有的时候你并不想这么作,那么就可使用( >> )来追加数据。
输入重定向
输入重定向正好和输出重定向相反。输入重定向将文件的内容重定向到命令,
bash shell 采用了( < )这个符号来实现这个功能。
command < inputfile
无论输入重定向仍是输出重定向,这个大于号和小于号都十分的形象,都是将数据从一边流向另外一边,这样就不会记错了。
指针$ bc < text1
3
$
一样输入重定向也有另外一种方式,叫作 内联输入重定向( << )这样是能够从命令行输入数据,使用的方式是这样的。
command << marker
data
marker
$ bc << EOF
1+2
EOF
3
$
管道
有的时候你须要将一个命令的输出,做为另外一个命令的输入,这样也能够用重定向来解决这个问题,
将一个命令的输出重定向到一个文件,再将文件重定向做为另外一个命令的输入,
可是我想你可能不会喜欢这么作,这显得很笨拙。
因此就有了管道( | )这个命令,
command1 | command2
管道的连接并非一个一个地运行,实际上它们是同时运行这两个命令的,在系统内部将它们链接起来。在第一个命令产生输出的同时,输出会当即送给第二个命令,传输数据不会用到任何中间文件或缓冲区。日志
理解输入输出
有的时候你可能并非想将数据的全部内容都显示在显示器上,有的你可能想保存在文本中,有的显示在显示器上,有的丢弃掉不要。
那么下面我门就了解一下这方面的内容。code
文件描述符
在Linux系统中每一个对象都是看成文件来处理的,这之中就有输入和输出的过程,那么就用文件描述符来标识每一个文件对象。
文件描述符标识着对应的文件,每一个过程当中最多可使用9个标识符,分别是( 0~8 ) 9个文件描述符。
bash shell 保留了( 0, 1, 2 )这三个文件描述符,其他的( 3~8 )的文件标识符用户能够自行定义使用。
( 0 )标识STDIN 标准输入
( 1 )标识STDOUT 标准输出
( 2 )标识STDERR 标准错误对象
STDIN表明的是标准输入,输入能够来自不少方面,对于你如今使用的电脑最多见的应该就是键盘。input
STDOUT表明的是标准输出,如今你若是在使用终端,那么输出的就是显示器上,
那么这个输出也是能够被重定向的,可能输出到某个文件中。date
STDERR这个就是标准错误,若是你将一个命令重定向到一个文件,
若是结果正确了,的确不会有任何输出,可是若是出现了错误提示,那么你会发现它仍是显示在了屏幕上。
file$ kkqaz > text1
bash: kkqaz: 未找到命令...
$
这个时候咱们已经将文件的输出重定向到了text1中,kkqaz显然不是一个命令,
这个时候它提示bash: kkqaz: 未找到命令...
,这段信息并无被重定向,
这就是由于,shell是经过特殊的文件标识符来处理错误信息的,
这就是STDERR,虽然STDOUT和STDERR都指向相同的地方,都会将他们的内容输入到显示器上。
可是当你使用 ( > )将STDOUT重定向的时候,STDERR并不会也跟着一个被重定向。
错误重定向
那么应该如何解决这个问题?其实只要在前面加上文件标识符就能够了。
$ kkqaz 2> text1
$ cat text1
bash: kkqaz: 未找到命令...
$
不过要注意的是文件标识符要紧挨着( > )否则就会出错。
那么若是你想将STDOUT和STDERR都重定向到文件中应该怎么办,其实只要使用两个重定向就能够实现。
$ ls -l text1 abc 1>text2 2>text3
$ cat text2
-rw-rw-r--. 1 forever forever 32 11月 9 13:21 text1
$ cat text3
ls: 没法访问abc: 没有那个文件或目录
$
这样就能够将信息和错误信息都输入到了文件中,而且将他们分开了。
同时若是你想将信息和错误信息,都输入到一个文件中,那也是能够的。
你只要使用 &>就能够将输出和错误信息都输出到同一个文件中。
$ ls -l text1 abc def &>text2
$ cat text2
ls: 没法访问abc: 没有那个文件或目录
ls: 没法访问def: 没有那个文件或目录
-rw-rw-r--. 1 forever forever 0 11月 9 13:38 text1
$
从文件中你能够看出在重定向时,输出的结果并非按照你预期的顺序输出的,
而是错误信息的的优先级更高一些,这样就井井有理了。
也方便了你能够到一个地方去寻找信息。
在脚本中时使用重定向
刚才已经熟悉了在命令行中进行重定向,那么接下来就来了解一下在脚本应如何使用吧。
在脚本中的重定向就分为以下两种:
1、临时重定向。
2、永久重定向。
临时重定向
当你向在脚本中输出一段错误提示的时候,你就能够这么作。
echo "error data" >&2
若是你熟悉C语言的指针,我想这种形式对你来讲会比较友好,也更容易理解。
$ cat shell6
#!/bin/bash
echo "This is an error" >&2
echo "This is output"
$./shell6
This is an error
This is output
$
两句话都输出了,好像看不出什么不一样,换个方式试试看。
$ ./shell6 1>text1
This is an error
$ ./shell6 2>text1
This is output
$
看起来不错你的错误信息和正常输出已经被区分出来了。
永久重定向
若是脚本中只有少许的输出,使用临时重定向的确是不错的办法,
可是当脚本中有大量的输出的时候,在每一句输出后都进行重定向那就太麻烦了。
那么就可使用exec命令来告诉执行期间重定向到某个特定的文件描述符。
$ cat shell6
#!/bin/bash
exec 1>text2
echo "This is output"
$ ./shell6
$ cat text2
This is output
$
脚本中重定向输入
咱们能够将输出重定向到其余位置,那么咱们也能够将STDIN从键盘重定向到其余位置。
最开始i重定向输出的方法在这里仍是可使用的。
固然仍是可使用exec命令的。
exec 0< inputfile
这个命令执行后,全部的输入都会从inputfile文件中读取。
$ cat inputtext
This is the first line
This is the second line
This is the third line
$ cat shell7
#!/bin/bash
exec 0< inputtext
count=1
while read line
do
echo "$count: $line"
count=$[ $count + 1 ]
done
$ ./shell7
This is the first line
This is the second line
This is the third line
$
这里当read想要读取用户从键盘输入的信息的时候就会从inputtext中读取数据。
若是你要处理读取文件的时候这就是一个绝佳的办法。
本身的重定向
系统默认的只有三个文件描述符,可是有的时候三个标准文件描述符并非很够用。
不过不用担忧,还记得前面提过还有其余6个文件描述符,那些文件描述符你均可以在脚本中给他们进行定义。
本身的文件描述符
咱们仍是可使用exec命令定义文件描述符
exec 3>text
$ cat shell8
#!/bin/bash
exec 3> text1
echo "This is the first one" >&3
exec 3>text2
echo "This is the second one" >&3
$ ./shell8
$ cat text1
This is the first one
$ cat text2
This is the second one
$
结果果真如你所向的那样,重定向的内容都输入到了相应的文件呢中,并无显示在显示在显示器上。
重定向文件描述符
在你重定向标准文件描述符,若是你想再恢复原来所指向的地方,你发现不知道应该重定向到哪里了。
下面就说一说如何将重定向的文件描述符恢复。
咱们将STDOUT重定向到了文件outputfile,当将部分输出到了文件中后,咱们还有部分的想要显示到屏幕的时候,这个时候咱们发现缺乏一个重定向的位置用来恢复。
那么这个时候咱们就一个普通的文件描述符重定向到STDOUT,而后再将STDOUT重定向,在STDOUT的重定向使用完毕后,咱们再用普通的文件描述符,来让STDOUT重定向到原来指向的位置。
下面仍是看一下实例吧。
$ cat shell9
#!bin/bash
exec 3>&1
exec 1>outputfile
echo "This will export to outputfile"
exec 1>&3
echo "This will output to display"
$ ./shell9
This will output to display
$ cat outputfile
This will export to outputfile
$
最开始咱们将文件描述符3重定向到了STDOUT,这样3就保存了原来的STDOUT所指向的位置,方便以后能够恢复。
随后将STDOUT重定向到了outputfile文件,这样在这个脚本中接下来的标准输出都是输出到了文件中。
在使用完这个后咱们将标准输出,有重定向到了原来STDOUT所指向的位置,也是如今的文件描述符3,因此将STDOUT重定向到3所指向的位置。
这样STDOUT的有将信息输出到了显示器上。
固然你使用这种方法的时候,固然没有必要像前面这样只有不多的输出的时候使用了,exec命令也是要在有大量的信息,都要输出到一样的位置的时候使用这个命令就很划算了。
读写文件描述符
咱们还能够用一个文件描述符,来进行对一个文件的输入和输出。
可是因为这个文件描述符是一个单独的对象,因此不论是读或者写,都会从上次执行结束的位置开始。
因此有的时候结果可能怪怪的。
$ cat shell10
#!/bin/bash
exec 3<>text3
read line <&3
echo "Hello" >&3
$ cat text3
This is a first text
This is a second text
This is a third text
$ ./shell10
$ cat text3
This is a first text
Hello
s a second text
This is a third text
$
关闭文件描述符
若是你再也不想使用一个文件描述符,那么就咱们这里给你提供一种方法。
exec 3>&-
这样就会关闭文件描述符3,那么若是你再使用就会出现错误。
最后咱们说一下,有的时候你不想将命令产生的一些如错误信息的输出,也不想保存在任何地方。
这样咱们能够将输出重定向到/dev/null中,这样你不想要的信息就不会在任何地方出现了。
$ ls > /dev/null $ cat /dev/null $/dev/null文件就像他的文件名同样什么也没有。 一样你还能够用经过将/dev/null文件中的内容重定向到文件中,来实现清空文件。