这一篇讲一下重定向

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

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

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

输出重定向

输出重定向最基本的就是将命令的输出重定向到文件中,bash shell 采用了( > ) 这个符号来实现这个功能。

command > outputfile

这样本应该在显示器上显示的内容就保存在了文件中。

  1. #!/bin/bash
  2. today=\`date +%y%m%d\`
  3. echo $today
  4. ls -al > log.$today
  1. $ ./shell5
  2. 171108
  3. $
  1. $ cat log.171108
  2. -rw-rw-r--. 1 forever forever 0 11 8 19:44 log.171108
  3. -rwxrw-r--. 1 forever forever 84 11 8 17:21 shell1
  4. -rwxrw-r--. 1 forever forever 45 11 8 18:25 shell2
  5. -rwxrw-r--. 1 forever forever 187 11 8 18:42 shell3
  6. -rwxrw-r--. 1 forever forever 50 11 8 18:52 shell4
  7. -rwxrw-r--. 1 forever forever 66 11 8 19:44 shell5
  8. ......
  9. $

这样就将命令的输出重定向到了log.$today中,log.$today这也是日志文件获取时间的一种方式。

( > )使用的时候就会将原有文件覆盖。但是有的时候你并不想这么做,那么就可以使用( >> )来追加数据。

输入重定向

输入重定向正好和输出重定向相反。输入重定向将文件的内容重定向到命令,

bash shell 采用了( < )这个符号来实现这个功能。

command < inputfile

不管输入重定向还是输出重定向,这个大于号和小于号都十分的形象,都是将数据从一边流向另一边,这样就不会记错了。

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

  4. command << marker

  5. data

  6. marker
  7. $ bc  1+2
  8. > EOF
  9. 3
  10. $ 
  11. 管道

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

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

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

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

  16. command1 | command2

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

  18. 理解输入输出

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

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

  21. 文件描述符

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

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

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

  25. ( 0 )标识STDIN 标准输入

  26. ( 1 )标识STDOUT 标准输出

  27. ( 2 )标识STDERR 标准错误

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

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

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

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

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

  33. $ kkqaz > text1
  34. bash: kkqaz: 未找到命令...
  35. $ 
  36. 这个时候我们已经将文件的输出重定向到了text1中,kkqaz显然不是一个命令,

  37. 这个时候它提示bash: kkqaz: 未找到命令...,这段信息并没有被重定向,

  38. 这就是因为,shell是通过特殊的文件标识符来处理错误信息的,

  39. 这就是STDERR,虽然STDOUTSTDERR都指向相同的地方,都会将他们的内容输入到显示器上。

  40. 但是当你使用 ( > )将STDOUT重定向的时候,STDERR并不会也跟着一个被重定向。

  41. 错误重定向

  42. 那么应该如何解决这个问题?其实只要在前面加上文件标识符就可以了。

  43. $ kkqaz 2> text1
  44. $ cat text1
  45. bash: kkqaz: 未找到命令...
  46. $
  47. 不过要注意的是文件标识符要紧挨着( > )不然就会出错。

  48. 那么如果你想将STDOUTSTDERR都重定向到文件中应该怎么办,其实只要使用两个重定向就可以实现。

  49. $ ls -l text1 abc 1>text2  2>text3
  50. $ cat text2
  51. -rw-rw-r--. 1 forever forever 32 11  9 13:21 text1
  52. $ cat text3
  53. ls: 无法访问abc: 没有那个文件或目录
  54. $
  55. 这样就可以将信息和错误信息都输入到了文件中,并且将他们分开了。

  56. 同时如果你想将信息和错误信息,都输入到一个文件中,那也是可以的。

  57. 你只要使用&>就可以将输出和错误信息都输出到同一个文件中。

  58. $ ls -l text1 abc  def &>text2
  59. $ cat text2
  60. ls: 无法访问abc: 没有那个文件或目录
  61. ls: 无法访问def: 没有那个文件或目录
  62. -rw-rw-r--. 1 forever forever 0 11  9 13:38 text1
  63. $
  64. 从文件中你可以看出在重定向时,输出的结果并不是按照你预期的顺序输出的,

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

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

  67. 在脚本中时使用重定向

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

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

  70. 一、临时重定向。

  71. 二、永久重定向。

  72. 临时重定向

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

  74. echo "error data" >&2

  75. 如果你熟悉C语言的指针,我想这种形式对你来说会比较友好,也更容易理解。

  76. $ cat shell6
  77. \#!/bin/bash
  78. echo "This is an error" >\&2
  79. echo "This is output"
  80. $./shell6
  81. This is an error
  82. This is output
  83. $
  84. 两句话都输出了,好像看不出什么不同,换个方式试试看。

  85. $ ./shell6 1>text1
  86. This is an error
  87. $ ./shell6 2>text1
  88. This is output
  89. $
  90. 看起来不错你的错误信息和正常输出已经被区分出来了。

  91. 永久重定向

  92. 如果脚本中只有少量的输出,使用临时重定向的确是不错的办法,

  93. 但是当脚本中有大量的输出的时候,在每一句输出后都进行重定向那就太麻烦了。

  94. 那么就可以使用exec命令来告诉执行期间重定向到某个特定的文件描述符。

  95. $ cat shell6
  96. \#!/bin/bash
  97. exec 1>text2
  98. echo "This is output"
  99. $ ./shell6
  100. $ cat text2
  101. This is output
  102. $ 
  103. 脚本中重定向输入

  104. 我们可以将输出重定向到其他位置,那么我们也可以将STDIN从键盘重定向到其他位置。

  105. 最开始i重定向输出的方法在这里还是可以使用的。

  106. 当然还是可以使用exec命令的。

  107. exec 0
  108. 这个命令执行后,所有的输入都会从inputfile文件中读取。
  109. $ cat inputtext
  110. This is the first line
  111. This is the second line
  112. This is the third line
  113. $ cat shell7
  114. \#!/bin/bash
  115. exec 0
  116. 这里当read想要读取用户从键盘输入的信息的时候就会从inputtext中读取数据。

  117. 如果你要处理读取文件的时候这就是一个绝佳的办法。
  118. 自己的重定向

  119. 系统默认的只有三个文件描述符,但是有的时候三个标准文件描述符并不是很够用。

  120. 不过不用担心,还记得前面提过还有其他6个文件描述符,那些文件描述符你都可以在脚本中给他们进行定义。
  121. 自己的文件描述符

  122. 我们还是可以使用exec命令定义文件描述符
  123. exec 3>text
  124. $ cat shell8
  125. \#!/bin/bash
  126. exec 3> text1
  127. echo "This is the first one" >&3
  128. exec 3>text2
  129. echo "This is the second one" >&3
  130. $ ./shell8
  131. $ cat text1
  132. This is the first one
  133. $ cat text2
  134. This is the second one
  135. $ 
  136. 结果果然如你所向的那样,重定向的内容都输入到了相应的文件呢中,并没有显示在显示在显示器上。

  137. 重定向文件描述符

  138. 在你重定向标准文件描述符,如果你想再恢复原来所指向的地方,你发现不知道应该重定向到哪里了。

  139. 下面就说一说如何将重定向的文件描述符恢复。




  140. 我们将STDOUT重定向到了文件outputfile,当将部分输出到了文件中后,我们还有部分的想要显示到屏幕的时候,这个时候我们发现缺少一个重定向的位置用来恢复。

  141. 那么这个时候我们就一个普通的文件描述符重定向到STDOUT,然后再将STDOUT重定向,在STDOUT的重定向使用完毕后,我们再用普通的文件描述符,来让STDOUT重定向到原来指向的位置。

  142. 下面还是看一下实例吧。

  143. $ cat shell9
  144. \#!bin/bash
  145. exec 3>&1
  146. exec 1>outputfile
  147. echo "This will export to outputfile"
  148. exec 1>&3
  149. echo "This will output to display"
  150. $ ./shell9
  151. This will output to display
  152. $ cat outputfile
  153. This will export to outputfile
  154. $ 
  155. 最开始我们将文件描述符3重定向到了STDOUT,这样3就保存了原来的STDOUT所指向的位置,方便之后可以恢复。

  156. 随后将STDOUT重定向到了outputfile文件,这样在这个脚本中接下来的标准输出都是输出到了文件中。

  157. 在使用完这个后我们将标准输出,有重定向到了原来STDOUT所指向的位置,也是现在的文件描述符3,所以将STDOUT重定向到3所指向的位置。

  158. 这样STDOUT的有将信息输出到了显示器上。




  159. 当然你使用这种方法的时候,当然没有必要像前面这样只有很少的输出的时候使用了,exec命令也是要在有大量的信息,都要输出到同样的位置的时候使用这个命令就很划算了。

  160. 读写文件描述符

  161. 我们还可以用一个文件描述符,来进行对一个文件的输入和输出。

  162. 但是由于这个文件描述符是一个单独的对象,所以不管是读或者写,都会从上次执行结束的位置开始。

  163. 所以有的时候结果可能怪怪的。

  164. $ cat shell10
  165. \#!/bin/bash
  166. exec 3text3
  167. read line &3
  168. $ cat text3
  169. This is a first text
  170. This is a second text
  171. This is a third text
  172. $ ./shell10
  173. $ cat text3
  174. This is a first text
  175. Hello
  176. s a second text
  177. This is a third text
  178. $ 
  179. 关闭文件描述符

  180. 如果你不再想使用一个文件描述符,那么就我们这里给你提供一种方法。

  181. exec 3>&-


  182. 这样就会关闭文件描述符3,那么如果你再使用就会出现错误。




  183. 最后我们说一下,有的时候你不想将命令产生的一些如错误信息的输出,也不想保存在任何地方。

  184. 这样我们可以将输出重定向到/dev/null中,这样你不想要的信息就不会在任何地方出现了。

  185. $ ls > /dev/null
  186. $ cat /dev/null
  187. $ 
  188. /dev/null文件就像他的文件名一样什么也没有。

  189. 同样你还可以用通过将/dev/null文件中的内容重定向到文件中,来实现清空文件。

  190. 											

    Shell编程学习之重定向的更多相关文章

      1. Linux shell 编程学习脚手架
      1. linux body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-t ...

      1. shell编程学习之使用jqjson数据进行提取
      1. shell编程学习之使用jqjson提取 jq命令允许直接在命令行下对JSON进行操作,包括分片.过滤.转换等 ,jq是用C编写,没有运行时依赖,所以几乎可以运行在任何系统上.预编译的二进制文件可以 ...

      1. shell编程学习笔记之sed编辑器
      1. shell编程中,大多数处理的都是文本文件.对文本文件进行处理除了使用交互式文本编辑器(vi[m],gedit......)也可以使用另外一类:流编辑器. 流编辑器:使用预定义的编辑规则来对文本进行 ...

      1. Linux Shell编程学习笔记——目录(附笔记资源下载)
      1. LinuxShell编程学习笔记目录附笔记资源下载 目录(?)[-] 写在前面 第一部分 Shell基础编程 第二部分 Linux Shell高级编程技巧 资源下载 写在前面 最近花了些时间学习She ...

      1. shell编程学习笔记(一):编写我的第一段代码
      1. 目前在学习Shell编程,我会把我的学习笔记记录在这里.大神可以直接略过~ 嗯,第一段代码,肯定是要输出Hello World了~ 以下蓝色字体的内容为linux命令,红色字体的内容为输出的内容: # ...

      1. Shell编程学习总结
      1. Shell编程总结 一.Hello World 新建文件test.sh 然后编辑代码: #!bin/bash/ echo “hello world !” cd 到目标目录下: chmod +x ./t ...

      1. shell编程学习1
      1. 1.shell是操作系统的终端命令行 (1)shell可以理解为软件系统提供给用户操作的命令行界面,可以说它是人机交互的一种方式.    (2)我们可以使用shell和操作系统.uboot等软件系统进 ...

      1. shell编程学习笔记【原创】
      1. 本文为本人学习笔记,如有转载请注明出处,谢谢 一.Bourne Shell 有如下四种变量: 用户自定义变量 位置变量,即命令行参数 预定义变量 环境变量 二.位置变量 $ 与键入的命令行一样,包含脚 ...

      1. (七)shell编程学习
      1. 1.shell程序练习:创建一个dir文件夹,在dir文件夹里再创建一个cd.c文件 首先vim hello.sh 2.shell中的变量定义和引用 (1)变量定义和初始化.shell是弱类型语言(语 ...

    1. 	
    2. 随机推荐

        1. Clouder Manager安装时出现please remove the following file: /etc/cloudera-scm-server/db.properties问题解决(图文详解)
        1. 问题详情 bigdata@ubuntucmbigdata1:/opt/softwares/cm-$ sudo ./cloudera-manager-installer.bin This install ...

        1. BoostrapTable-本地模式(一次性加在所有数据)
        1. 直接上代码 数据: [ { "id": "1001", "name": "yyq", "isAdmin&quo ...

        1. React.js 小书 Lesson3 - 前端组件化(二):优化 DOM 操作
        1. 作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson3 转载请注明出处,保留原文链接和作者信息. 看看上一节我们的代码,仔细留意一下 change ...

        1. Scroller类的使用总结
        1. Scroll类之所以不好理解是因为没有搞清楚View的绘制流程. 1)简单来讲 viewgroup重绘时依次会调用  dispatchDraw -- drawChild --child.compute ...

        1. js获取日期:前天、昨天、今天、明天、后天
        1. 前天,昨天,今天,明天,后天 <html> <head> <meta http-equiv="Content-Type" content=" ...

        1. Swift-数组
        1. 1.数组的定义  //OC 使用[]定义数组,Swift一样,但是没有@ //自动推导的结果[String]->表示数组中存的都是String //跟OC中的数组指定泛型类型  //Swift ...

        1. springmvc实现文件下载到Android手机设备pda
        1. 1:首先要添加相关得jar文件,在pom.xml <dependency> <groupId>commons-fileupload</groupId> <a ...

        1. 使用axios请求发送数据
        1. 之前一直没有用成功,今天看了一些博客,学会了使用axios插件 1.首先就是下载依赖啦 2.main.js import axios from 'axios'Vue.prototype.$axios ...

        1. ArcGIS 10.2之地图服务的发布、使用
        1. 2.发布地图服务 2.1 地图服务器的建立 打开ArcCatalog,在左侧的GIS Servers下,双击Add ArcGIS Server, 弹出添加界面,选择,Administer GIS服务项 ...

        1. ArcSDE空间数据库中SDE用户使用探讨(转)
        1. ArcSDE作为空间数据库解决方案,应用非常广泛,本短文将尝试描述SDE的工作机制,简要说明空间数据 库中SDE用户的使用方法. ArcSDE如何工作 ArcSDE属于中间件技术,其本身并不能够存储空 ...

      1. 							
      2.