3.6 重定向(Redirections)
在一个命令执行之前,shell 可以使用一个特殊符号将其输入和输出解释为重定向。重定向允许对命令的文件控制句柄进行复制、打开和关闭操作,使其引用到不同的文件,并且能改变命令读取和写入的文件。重定向也可以用于在当前 shell 执行环境中改变文件控制句柄。下面的重定向操作符可能出现在命令前面或后面,或在一个简单命令的任意位置。重定向根据其出现的位置,依照从左到右的顺序进行处理。
每一个重定向前面可以带有一个文件描述符数字,也可使用“{varname}”形式的单词代替数字。在这种情况下, shell 将为每一个重定向操作符(除了“>&-”和“<&-”)分配一个大于 10 的文件描述符给“{varname}”。如果在“>&-”或“<&-”前面是“{varname}”,则“varname”值定义为文件描述符关闭。如果提供了“{varname}”,则重定向的存留将超出命令范围,这允许 shell 程序员手动管理文件描述符的生命周期。
在下面的描述中,如果省略了文件描述符数字,并且重定向操作符的第一个字符是“<”,则重定向引用到标准输入(即文件描述符 0)。如果重定向操作符的第一个字符是“>”,则重定向引用到标准输出(即文件描述符 1)。
在下面描述中跟随在重定向操作符后的单词,除非有其它注释,都可由大括号扩展、波浪号扩展、参数扩展、命令替换、算术扩展、引用移除、文件名扩展和单词分割生成。如果扩展出多于一个单词的结果,Bash 则报错。
注意,重定向的顺序是很重要的。例如,命令
ls > dirlist 2>&1
是将标准输出(即文件描述符 1)和标准报错(即文件描述符 2)定向到文件“dirlist”中去,而命令
ls 2>&1 > dirlist
只将标准输出定向到文件“dirlist”中,因为在标准输出重定向到文件“dirlist”之前就将标准报错的一个副本复制到标准输出了。
在下表的描述中,Bash 会特殊处理一些用于重定向的文件。如果运行 Bash 的操作系统提供了这些特殊文件,则 bash 会使用它们;否则 Bash 将在内部模拟这些文件以及下面所描述的行为。
| 文件 | 描述 |
|---|---|
| /dev/fd/fd | 如果“fd”是一个有效整数,则复制文件描述符“fd”。 |
| /dev/stdin | 复制文件描述符 0。 |
| /dev/stdout | 复制文件描述符 1。 |
| /dev/stderr | 复制文件描述符 2。 |
| /dev/tcp/host/port | 如果“host”是一个有效的主机名或 Internet 地址,并且“port”是一个整数或服务名,Bash 则试图打开一个相应的 TCP 套接层。 |
| /dev/udp/host/port | 如果“host”是一个有效的主机名或 Internet 地址,并且“port”是一个整数或服务名,Bash 则试图打开一个相应的 UDP 套接层。 |
打开或创建文件失败,会引起重定向的失败。
在重定向中使用文件描述符大于 9 时要特别小心,因为其可能会与 shell 内部使用的文件描述符相冲突。
3.6.1 输入重定向(Redirecting Input)
输入重定向会引发在文件描述符“n”上打开由“word”扩展生成的文件名指定的文件进行读取。如果没有指定“n”,则是在标准输入(即文件描述符为 0)上读取。
输入重定向的一般格式是:
[n]<word
3.6.2 输出重定向(Redirecting Output)
输出重定向会引发在文件描述符“n”上打开由“word”扩展生成的文件名指定的文件进行写入。如果没有指定“n”,则是在标准输出(即文件描述符为 1)上写入。如果文件不存在,则创建该文件;如果文件存在,则将其大小删减为零。
输出重定向的一般格式是:
[n]>[|]word
如果重定向操作符是“>”,并且内建命令 set 的选项“noclobber”开启了,再如果从“word”扩展生成的文件名的文件是存在的并且是一个常规文件,则重定向会失败。如果重定向操作符是“>|”,或操作符是“>”并且“noclobber”没有开启,则会试图进行重定向,即使“word”所产生的文件名存在。
3.6.3 输出重定向追加(Appending Redirected Output)
这种方式的输出重定向会在文件描述符“n”上打开由单词“word”扩展所产生的文件名的文件,用于进行追加写入。或如果“n”没有指定,则是在标准输出(即文件描述符为 1)上进行。如果文件不存在,则创建该文件。
追加输出的一般格式是:
[n]>>word
3.6.4 标准输出和标准报错重定向(Redirecting Standard Output and Standard Error)
这种结构允许标准输出(即文件描述符 1)和标准报错(即文件描述符 2)都被重定向到由“word”扩展得到的文件名的文件。
标准输出和标准报错重定向有两种格式:
&>word
和
>&word
在两种格式中推荐使用第一种格式。这在语义上等同于>word 2>&1。
在使用第二种格式时,“word”不能扩展成一个数字或“-”。如果这么做了,出于兼容性原因会应用为另外一种重定向操作符(参见下面的《文件描述符复制》)。
3.6.5 标准输出和标准报错追加(Appending Standard Output and Standard Error)
这种结构允许标准输出(即文件描述符 1)和标准报错(即文件描述符 2)都被重定向追加到由“word”扩展得到的文件名的文件。
标准输出和标准报错追加格式是:
&>>word
这在语义上等同于>>word 2>&1(参见下面的《文件描述符复制》)。
3.6.6 多行字符串重定向(Here Documents)
这种类型的重定向指示 shell 从当前输入源进行读取,直到读取到再次出现只包含“word”的单行(不带尾部空白的)时结束。读取的所有行被用作命令的标准输入(或如果指定了“n”,则是文件描述符“n”)。
多行字符串重定向的格式是:
[n]<<[-]word
here-document
delimiter
不会在“word”上执行参数和变量扩展、命令替换、算术扩展或文件名扩展。如果“word”的任意部分被引起来了,则“delimiter”是“word”引用移除后的结果,并且“here-document”里的所有行不会进行扩展。如果“word”是未被引起来的,则“here-document”的所有行可以由参数扩展、命令替换和算术扩展生成,字符序列“\newline”会被忽略,并且字符“\”、“$”和“`”必须使用“\”进行转义。
如果重定向操作符是“<<-”时,所有输入行的起始位置的 tab 字符都将被去除,这也包括“delimiter”行的。这允许在 shell 脚本中的“here-document”使用缩进样式。
3.6.7 单行字符串重定向(Here Strings)
这是多行字符串重定向的一个变体,格式是:
[n]<<< word
“word”可以由波浪号扩展、参数和变量扩展、命令替换、算术扩展和引用移除生成。文件名扩展和单词分割不会在这里执行。这提供了一个带有换行的单行字符串作为命令的标准输入(或文件描述符“n”,如果“n”指定了的话)。
3.6.8 文件描述符复制(Duplicating File Descriptors)
重定向操作符
[n]<&word
用于复制输入文件描述符。如果“word”扩展为一位或多位数字,则由“n”表示的文件描述符将成为该文件描述符的一个副本。如果在“word”中的数字没有指定打开一个用于输入的文件描述符,则会出现重定向报错。如果“word”评估为“-”,文件描述符“n”将被关闭。如果未指定“n”,则使用标准输入(即文件描述符 0)。
操作符
[n]>&word
用于复制输出文件描述符。如果没有指定“n”,则使用标准输出(即文件描述符 1)。如果“word”中的数字未指定打开一个输出文件描述符,则出现重定向报错。如果“word”是“-”,则关闭文件描述符“n”。在特殊情况下,如果省略了“n”,并且 word 没有扩展为一位或多位数字或“-”,则会像上面章节描述的那样对标准输出和标准报错进行重定向。
3.6.9 文件描述符移动(Moving File Descriptors)
重定向操作符
[n]<&digit-
将文件描述符“digit”移动到文件描述符“n”。或如果未指定“n”,则移动到标准输入(即文件描述符 0)。在“digit”复制到“n”后将其关闭。
同样地,重定向操作符
[n]>&digit-
将文件描述符“digit”移动到文件描述符“n”,或如果未指定“n”,则移动到标准输出(即文件描述符 1)。
3.6.10 用于读取和写入的文件描述符打开(Opening File Descriptors for Reading and Writing)
重定向操作符
[n]<>word
会打开由“word”扩展得到的文件名的文件,用于在文件描述“n”上进行读取和写入。或如果没有指定“n”,则文件描述符为 0。如果文件不存在,则创建它。