重定向（REDIRECTION）
=================

在命令执行前，它的输入和输出可能被重定向（`redirect`），使用一种`shell`可以解释的特殊记法。
重定向也可以用于为当前`shell`执行环境打开和关闭文件。
下列重定向操作符可以前置或者放在简单命令（`simple command`）之中的任何位置，或者放在命令之后。
重定向是以出现的顺序进行处理的，从左到右。

下列描述中，如果文件描述符被忽略，并且第一个重定向操作符是`<`，那么重定向指的是标准输入（文件描述符是`0`）。
如果重定向操作符的第一个字符是`>`，那么重定向指的是标准输出（文件描述符是`1`）。

下列描述中，重定向操作符之后的词如果没有特殊说明，都要经过brace expansion, tilde expansion, parameter expansion, command substitution, arithmetic expansion, quote removal, pathname expansion, 还有 word splitting。
如果扩展为多于一个词，`bash`将报错。

注意重定向的顺序非常重要。例如，命令

```bash
ls > dirlist 2>&1
```

将标准输出和标准错误重定向到文件`dirlist`，而命令

```bash
ls 2>&1 > dirlist
```

只会将标准输出重定向到文件`dirlist`，因为在标准输出被重定向到文件`dirlist`中之前，标准错误被复制为标准输出。

一些文件名在重定向中被`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`连接。

打开或创建文件错误将导致重定向出错。  

重定向输入
-----------------

重定向输入（`Redirecting Input`）使得以`word`扩展结果为名的文件被打开并通过文件描述符`n`读取，如果没有指定`n`那么就作为标准输入（文件描述符为`0`）读取。

重定向输入的一般形式是：

```bash
[n]<word
```
 
重定向输出
---------------

重定向输出（`Redirecting Output`）使得以`word`扩展结果为名的文件被打开并通过文件描述符`n`写入，如果没有指定`n`那么就作为标准输出（文件描述符为`1`）写入。

重定向的一般形式是：

```bash
[n]>word
```

如果重定向操作符是`>`，并且启用了内建命令`set`的`noclobber`选项，那么如果`word`扩展后得到的文件名存在并且是一个普通的文件，重定向将失败。
如果重定向操作符是`>|`, 或者重定向操作符是`>`并且没有启用内建命令`set`的`noclobber`选项，那么即使`word`得出的文件名存在，也会尝试进行重定向。

追加式重定向输出（`Appending Redirected Output`)
---------------

这种方式的输出重定向使得以`word`扩展结果为名的文件被打开并通过文件描述符`n`从尾部添加。
如果没有指定`n`就使用标准输出（文件描述符`1`）。如果文件不存在，它将被创建。

重定向的一般形式是：

```bash
[n]>>word
```
 

Redirecting Standard Output and Standard Error

`bash`允许使用这种结构将标准输出和标准错误（文件描述符`1`和`2`) 重定向到以`word`扩展结果为名的文件中。

有两种重定向标准输出/标准错误的形式：

```bash
&>word
```

还有

```bash
>&word
```

两种形式中，推荐使用第一种。它与

```bash
>word 2>&1
```
在语义上等价。

Here Documents
---------------

这种重定向使得`shell`从当前源文件读取输入，直到遇到仅包含`word`的一行（并且没有尾部空白）为止。
直到这一点的所有行被用作 命令的标准输入。

`here-document`的格式是：

```bash
<<[-]word
        here-document
delimiter
```

不会对`word`进行参数扩展、命令替换、算术扩展或者路径名扩展。
如果`word`中任何字符是引用的，`delimiter`将是对`word`进行引用删除的结果，`here-document`中的行不会被扩展。
如果`word`没有被引用，`here-documnet`中的所有行都要经过参数扩展、命令替换和算术扩展。
在后一种情况下，字符序列`\<newline>`被忽略；必须用`\`来引用字符`\`、`$`和 `\``。

如果重定向操作符是`<<-`, 那么所有前导的`tab`字符都被从输入行和包含`delimiter`的行中删除。
这样使得`shell`脚本中的`here-document`可以被更好地缩进。

Here Strings
---------------

`here-document`的变种，形式是

```bash
<<<word
```

`word`被扩展，提供给命令作为标准输入。

复制文件描述符（Duplicating File Descriptors）
-------------------------

重定向操作符

```bash
[n]<&word
```

用于复制文件描述符。如果`word`扩展为一个或多个数字，`n`代表的文件描述符将成为那个文件描述符的复制。
如果`word`中的数字并未指定一个被用于读取的文件描述符，将产生一个重定向错误。
如果`word`扩展为`-`，文件描述符`n`将被关闭。
如果没有指定`n`，将使用标准输入（文件描述符`0`）。

类似的，操作符

```bash
[n]>&word
```

用于复制输出文件描述符。
如果没有指定`n`，将使用标准输出（文件描述符`1`）。
如果`word`中的数字并未指定一个被用于输出的文件描述符，将产生一个重定向错误。
特殊情况下，如果忽略了`n`，并且`word`并非扩展为一个或多个数字，标准输出和标准错误将被重定向，和前面描述的一样。

Moving File Descriptors
---------------------

重定向操作符

[n]<&digit-

将文件描述符`digit`移动为文件描述符`n`；如果没有指定`n`，则移动标准输入（文件描述符`0`）

`digit`复制为`n`之后就被关闭了。

类似的，重定向操作符

```bash
[n]>&digit-
```

将文件描述符`digit`移动为文件描述符`n`，或标准输出（文件描述符`1`），如果没有指定`n`的话。

Opening File Descriptors for Reading and Writing
----------------------

重定向操作符

```bash
[n]<>word
```

使得以`word`扩展结果为名的文件被打开，通过文件描述符`n`进行读写。
如果没有指定`n`那么就使用文件描述符`0`。如果文件不存在，它将被创建。
