# I/O重定向

## I/O 重定向

在UNIX系统中，获取输入和写入输出的流是预定义的。总是有三个默认文件打开：

* `stdin` 是输入数据源（键盘）
* `stdout` 是输出数据源（屏幕）
* `stderr` 是标准错误输出源（错误消息输出到屏幕）

这些以及任何其他打开的文件都可以被重定向。重定向简单地说就是捕获来自文件、命令、程序、脚本甚至脚本内代码块的输出，并将其作为输入发送到另一个文件、命令、程序或脚本。

### 基本重定向操作

```bash
## command_output >
# 将stdout重定向到文件
# 如果文件不存在则创建，否则覆盖它
$ ls -la > ls_result.txt

## : > filename
# '>' 将文件 'filename' 截断为零长度
# 如果文件不存在，创建零长度文件（与 'touch' 效果相同）
# ':' 用作虚拟占位符，不产生输出
$ : > empty_file.txt

## command_output >>
# 将stdout重定向到文件
# 如果文件不存在则创建，否则追加到它
$ ls -la >> ls_result.txt
```

### 文件描述符重定向

每个打开的文件都会被分配一个[文件描述符](/linux-an-quan/overview/file-descriptor.md)。`stdin`、`stdout`和`stderr`的文件描述符分别是`0`、`1`和`2`。对于打开的额外文件，保留描述符`3`到`9`。

```bash
## m>n
# 'm' 是文件描述符，如果未显式设置则默认为1
# 'n' 是文件名
# 文件描述符 'm' 重定向到文件 'n'
$ ls -la > ls_result.txt
$ ls -la 1>ls_result.txt
$ ./script.sh 2>error.log

## m>&n
# 'm' 是文件描述符，如果未设置则默认为1
# 'n' 是另一个文件描述符
$ ./script.sh 2>&1 > log.txt

## &>filename
# 将stdout和stderr都重定向到文件 'filename'
$ ./script.sh &>filename

## < filename
# 从文件接受输入
$ grep "*some*" <filename
$ grep "*some*" 0<filename
```

### 高级重定向技巧

#### 合并输出流

```bash
# 将stderr重定向到stdout
$ command 2>&1

# 将stdout和stderr都重定向到文件
$ command &> output.txt
$ command > output.txt 2>&1

# 将stdout重定向到文件，stderr重定向到另一个文件
$ command > stdout.txt 2> stderr.txt
```

#### 输入重定向

```bash
# 从文件读取输入
$ command < input.txt

# 从here document读取输入
$ command << EOF
line1
line2
EOF

# 从here string读取输入
$ command <<< "hello world"
```

#### 进程替换

```bash
# 将命令的输出作为文件使用
$ diff <(command1) <(command2)

# 将多个命令的输出合并
$ cat <(ls) <(pwd)
```

### 防止意外覆盖

你可以通过在shell中设置`noclobber`选项来确保没有任何重定向会破坏现有文件：

```bash
$ set -o noclobber
$ sort file.txt > file.txt
-bash: file.txt: cannot overwrite existing file

# 临时覆盖
$ sort file.txt >| file.txt

# 关闭noclobber
$ set +o noclobber
```

### 实用示例

#### 日志记录

```bash
# 将正常输出和错误分别记录到不同文件
$ ./script.sh > success.log 2> error.log

# 将所有输出记录到同一文件
$ ./script.sh > all.log 2>&1

# 同时输出到屏幕和文件
$ ./script.sh 2>&1 | tee output.log
```

#### 调试

```bash
# 仅显示错误
$ ./script.sh 2> error.log >/dev/null

# 静默模式（仅显示错误）
$ ./script.sh >/dev/null

# 丢弃所有输出
$ ./script.sh >/dev/null 2>&1
```

## 参考资料

* [How Unix Works: Become a Better Software Engineer](https://neilkakkar.com/unix.html) - 深入了解UNIX工作原理
* [Advanced Bash-Scripting Guide: I/O Redirection](https://tldp.org/LDP/abs/html/io-redirection.html) - 高级Bash脚本编写指南
* [Bash Redirections Cheat Sheet](https://mywiki.wooledge.org/BashGuide/InputAndOutput#Redirections) - Bash重定向速查表


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.cdxiaodong.life/linux-an-quan/overview/io-redirection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
