这一篇讲一下重定向

有些时候你想要保存某些命令产生的输出而不是在显示器上显示它。

为了应对这样的问题 bash shell 也就提供了一些重定向的操作符。

我们先了解一些基本的应用。

输出重定向

输出重定向最基本的就是将命令的输出重定向到文件中,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 

同样输入重定向也有另一种方式,叫做内联输入重定向( << )这样是可以从命令行输入数据,使用的方式是这样的。

command << marker

data

marker
$ bc  1+2
> EOF
3
$

管道

有的时候你需要将一个命令的输出,作为另一个命令的输入,这样也可以用重定向来解决这个问题,

将一个命令的输出重定向到一个文件,再将文件重定向作为另一个命令的输入,

但是我想你可能不会喜欢这么做,这显得很笨拙。

所以就有了管道( | )这个命令,

command1 | command2

管道的链接并不是一个一个地运行,实际上它们是同时运行这两个命令的,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会立即送给第二个命令,传输数据不会用到任何中间文件或缓冲区。

理解输入输出

有的时候你可能并不是想将数据的所有内容都显示在显示器上,有的你可能想保存在文本中,有的显示在显示器上,有的丢弃掉不要。

那么下面我门就了解一下这方面的内容。

文件描述符

在Linux系统中每个对象都是当作文件来处理的,这之中就有输入和输出的过程,那么就用文件描述符来标识每个文件对象。

文件描述符标识着对应的文件,每个过程中最多可以使用9个标识符,分别是( 0~8 ) 9个文件描述符。

bash shell 保留了( 0, 1, 2 )这三个文件描述符,其余的( 3~8 )的文件标识符用户可以自行定义使用。

( 0 )标识STDIN 标准输入

( 1 )标识STDOUT 标准输出

( 2 )标识STDERR 标准错误

STDIN代表的是标准输入,输入可以来自很多方面,对于你现在使用的电脑最常见的应该就是键盘。

STDOUT代表的是标准输出,现在你如果在使用终端,那么输出的就是显示器上,

那么这个输出也是可以被重定向的,可能输出到某个文件中。

STDERR这个就是标准错误,如果你将一个命令重定向到一个文件,

如果结果正确了,的确不会有任何输出,但是如果出现了错误提示,那么你会发现它还是显示在了屏幕上。

$ 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
$

从文件中你可以看出在重定向时,输出的结果并不是按照你预期的顺序输出的,

而是错误信息的的优先级更高一些,这样就井然有序了。

也方便了你可以到一个地方去寻找信息。

在脚本中时使用重定向

刚才已经熟悉了在命令行中进行重定向,那么接下来就来了解一下在脚本应如何使用吧。

在脚本中的重定向就分为如下两种:

一、临时重定向。

二、永久重定向。

临时重定向

当你向在脚本中输出一段错误提示的时候,你就可以这么做。

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文件中读取。
$ cat inputtext
This is the first line
This is the second line
This is the third line
$ cat shell7
\#!/bin/bash
exec 0 这里当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 3text3
read line &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文件中的内容重定向到文件中,来实现清空文件。

最新文章

  1. RabbitMQ 一二事(4) - 路由模式介绍
  2. CodeForces 416D (贪心)
  3. redis批量删除
  4. Hibernate征途(六)之数量和关系映射
  5. PHP学习笔记--入门篇
  6. 【BZOJ 1934】 [Shoi2007]Vote 善意的投票
  7. (四)值栈与OGNL
  8. 如何优化cocos2d程序的内存使用和程序大小:第二部分_(转)
  9. 迅雷API:实现文件下载
  10. springMVC项目异步错误处理请求Async support must be enabled on a servlet and for all filters involved in async
  11. maven私服搭建nexus介绍(二)
  12. CF 690C3. Brain Network (hard) from Helvetic Coding Contest 2016 online mirror (teams, unrated)
  13. Elasticsearch分片、副本与路由(shard replica routing)
  14. 【开发技术】视频URL采集
  15. 【代码笔记】Web-JavaScript-JavaScript表单验证
  16. 最简单的C#UDP通讯示例
  17. XamarinSQLite教程添加索引
  18. Leetcode 1.两数之和 By Python
  19. PyQt5--QFontDiaglog
  20. Javassist 字节码 简介 案例 MD

热门文章

  1. spring配置文件中util:properties和context:property-placeholder
  2. gitee 搭建自己的代码仓库
  3. 大数据 Big Data howto
  4. MySQL &#183; 引擎特性 &#183; InnoDB index lock前世今生
  5. 3n+1猜想
  6. 021-动态生成验证码jsp代码模板
  7. MVC视图之间调用方法总结
  8. SWIG 和 Python——c/c++与脚本交互
  9. HDU 5371——Hotaru&#39;s problem——————【manacher处理回文】
  10. Day4上午