流,管道以及序列

Bash有很强大的工具来处理程序之间的协同工作。使用流,我们能将一个程序的输出发送到另一个程序或文件,因此,我们能方便地记录日志或做一些其它我们想做的事。

管道给了我们创建传送带的机会,控制程序的执行成为可能。

学习如何使用这些强大的、高级的工具是非常非常重要的。

Bash接收输入,并以字符序列或 字符流 的形式产生输出。这些流能被重定向到文件或另一个流中。

有三个文件描述符:

代码 描述符 描述
0 stdin 标准输入
1 stdout 标准输出
2 stderr 标准错误输出

重定向让我们可以控制一个命令的输入来自哪里,输出结果到什么地方。这些运算符在控制流的重定向时会被用到:

Operator Description
> 重定向输出
&> 重定向输出和错误输出
&>> 以附加的形式重定向输出和错误输出
< 重定向输入
<< Here文档 语法
<<< Here字符串

以下是一些使用重定向的例子:

  1. # ls的结果将会被写到list.txt中
  2. ls -l > list.txt
  3. # 将输出附加到list.txt中
  4. ls -a >> list.txt
  5. # 所有的错误信息会被写到errors.txt中
  6. grep da * 2> errors.txt
  7. # 从errors.txt中读取输入
  8. less < errors.txt

管道

我们不仅能将流重定向到文件中,还能重定向到其它程序中。管道 允许我们把一个程序的输出当做另一个程序的输入。

在下面的例子中,command1把它的输出发送给了command2,然后输出被传递到command3

  1. command1 | command2 | command3

这样的结构被称作 管道

在实际操作中,这可以用来在多个程序间依次处理数据。在下面的例子中,ls -l的输出被发送给了grep,来打印出扩展名是.md的文件,它的输出最终发送给了less

  1. ls -l | grep .md$ | less

管道的返回值通常是管道中最后一个命令的返回值。shell会等到管道中所有的命令都结束后,才会返回一个值。如果你想让管道中任意一个命令失败后,管道就宣告失败,那么需要用下面的命令设置pipefail选项:

  1. set -o pipefail

命令序列

命令序列是由;&&&或者||运算符分隔的一个或多个管道序列。

如果一个命令以&结尾,shell将会在一个子shell中异步执行这个命令。换句话说,这个命令将会在后台执行。

;分隔的命令将会依次执行:一个接着一个。shell会等待直到每个命令执行完。

  1. # command2 会在 command1 之后执行
  2. command1 ; command2
  3. # 等同于这种写法
  4. command1
  5. command2

&&||分隔的命令分别叫做 序列。

与序列 看起来是这样的:

  1. # 当且仅当command1执行成功(返回0值)时,command2才会执行
  2. command1 && command2

或序列 是下面这种形式:

  1. # 当且仅当command1执行失败(返回错误码)时,command2才会执行
  2. command1 || command2

序列的返回值是序列中最后一个执行的命令的返回值。