简介

Linux 终端下的重定向功能在日常办公中经常被使用到,深入理解并熟练掌握 Bash Shell 的重定向将有助于提升办公效率。Bash Shell 下的重定向是通过文件描述符实现的,Linux 系统默认有三个标准的文件描述符:

  • stdin:标准输入,文件描述符 0
  • stdout:标准输出,文件描述符 1
  • stderr:标准错误,文件描述符 2

假设 Linux 终端设备为 /dev/tty0,则 Linux 系统下标准文件描述符在 Bash Shell 中与设备的映射关系如下:

一种简单好理解重定向符的方法:将 >/< 看做是赋值语句中的 =,前者的方向代表后者的赋值方向;将 & 看做是 $

重定向标准输出到文件

1
command >file

其中,> 操作符是输出重定向操作符。Bash 首先会尝试打开 file 文件,如果成功打开则将 command 的标准输出发送到 file 文件中,并将原来的内容覆盖;如果无法打开,则该条命令执行失败并报错。

command >file 等价于 command 1>file,这是因为 1 是输出重定向默认的文件描述符。该命令下,文件描述表与设备的映射关系如下:

重定向到文件的一般命令为 command n>file,其中 n 为需要重定向的文件描述符。

为了避免不小心覆盖已有文件,可以为当前 Shell 设置 noclobber 选项:

1
set -o noclobber

这样之后,如果 file 已经存在,>file 就是报错。在这种情况下,如果你确定一定要覆盖,可以使用 >| 操作符。

1
command >| file

重定向标准错误到文件

1
command 2>file

该命令下,文件描述符表与设备的映射关系如下:

定向标准输出和标准错误到文件

1
command &>file

其中,&> 操作符用来同时重定向 stdoutstderr。该命令下,文件描述符表与设备的映射关系如下:

重定向的先后顺序

一种等价于 &> 操作的重定向命令为:

1
command >file 2>&1

其中,先后出现了两次重定向:

  • 第一次是将 stdout 重定向到 file
  • 第二次是将 stderr 重定向到文件描述符 1,而 1 已经被重定向到 file,所以等价于 stderr 重定向到 file

该命令下,文件描述符表与设备的映射关系如下:

与之不同的是,如果将 2>&1 提前到 >file,则对应的含义完全不同:

1
command 2>&1 >file

其中,先后出现了两次重定向:

  • 第一次是将 stderr 重定向到 stdout,此时 stdout 映射到终端 /dev/tty0,故等价于 stderr 重定向到 /dev/tty0
  • 第二次是将 stdout 重定向到 file

该命令下,文件描述符表与设备的映射关系如下:

丢弃标准输出

1
command > /dev/null

/dev/null 是 Linux 系统中特殊的虚拟设备,其会将发送给它的所有内容丢弃。

重定向标准输入

1
command <file

其中,< 操作符是输入重定向操作符。Bash 首先会尝试打开 file 文件,如果成功打开则 file 中的内容重定向到 command 作为输入;如果无法打开,则该条命令执行失败并报错。

该命令下,文件描述符表与设备的映射关系如下:

重定向多条文本到标准输入

1
2
3
4
5
6
7
command <<EOF
your
multi-line
text
goes
here
EOF

其中,<<MARKER 操作符用来重定向文本内容。该命令会将两个 MARKER 中包裹的文件内容重定向到标准输入。

重定向单行文件到标准输入

1
command <<< "foo bar baz"

该命令等价于:

1
echo "foo bar baz" | command

固定重定向标准错误到文件

1
2
3
4
exec 2>file
command1
command2
...

exec 是 Linux Bash 内建命令,该命令会将 stderr 固定重定向到 file 文件,直到再次修改重定向或退出当前的 Bash Shell。

固定输入重定向文件描述符

1
exec 3<file

该命令会尝试打开 file 文件,并分配文件描述符 3 指定到 file,用于后续输入需要。比如:

1
grep "foo" <&3

如果想要关掉文件描述符 3,则可以使用以用命令:

1
exec 3>&-

固定输出重定向文件描述符

1
2
exec 4>file
echo "foo" >&4

与输入重定向文件描述符一样,如果想要关掉文件描述符 4,可以使用以下命令:

1
exec 4>&-

固定输入输出重定向文件描述符

1
exec 3<>file

合并多输出重定向到文件

1
(command1; command2) >file

重定向到文件和终端

1
command | tee file

tee 命令常用来将输出重定向到文件,同时又保留终端输出。其工作方式如下:

管道通信

Bash Shell 下的管道 | 可以用来在不同命令间通信,比如:

1
command1 | command2

该命令会将 command1 的标准输出和 command2 的标准输入连接,其对应的输入输出映射关系如下:

如果需要将 command1 的标准错误也发送给 command2,可以使用 |& 操作符:

1
command1 |& command2

或者先将 command1 的标准错误重定向到其标准输出,即等价于以下命令:

1
command1 2>&1 | command2

交换标准输出和标准错误

1
command 3>&1 1>&2 2>&3

分别重定向标准输出和标准错误

1
command > >(stdout_cmd) 2> >(stderr_cmd)

其中,>(...) 操作符会将 ...stdin 连接到一个匿名管道,这里即对应 commandstdout,再执行 ...

重定向备忘卡

参考文献