所谓 I/O 重定向简单来说就是一个过程,这个过程捕捉一个文件,或者命令,程序,脚本,甚至脚本中的代码块(code block)的输出,然后把捕捉到的输出,作为输入发送给另外一个文件,命令,程序,或者脚本。

输入、输出、流

Linux shell 是以字符序列或字符流的方式接收输入,发送输出。每个单独的字符之间是相互独立的。

无论字符流来自或去往文件、键盘、窗口、其它 I/O 设备,都可以用文件 I/O 技术来访问流。

Linux shell 使用三种标准的 I/O 流,用 文件描述符 表示。

文件描述符

File Descriptor

在 Linux 系统中,系统为每一个打开的文件指定一个文件描述符,以便系统对文件进行跟踪,文件描述符是一个数字,不同数字代表不同的含义。

默认情况下,系统占用了 3 个:

  • STDIN:标准输入流,为命令提供输入,描述符为 0,通常指键盘的输入

  • STDOUT:标准输出流,显示来自命令的输出,描述符为 1,通常指显示器的输出

  • STDERR:标准错误流,显示来自命令的错误信息,描述符为 2,通常也是定向到显示器

3-9 是保留的标识符,可以把这些标识符指定成标准输入,输出或者错误作为临时连接。通常这样可以解决很多复杂的重定向请求。

自定义文件描述符

可以使用 exec 命令创建自定义的文件描述符。

  • 为读取文件创建描述符
~]$ echo this is a test line > input.​txt
~]$ exec 3<input.​txt
~]$ cat <&3
this is a test line
  • 为写入文件创建描述符
~]$ exec 4>output.txt
~]$ echo newline >&4
~]$ cat output.txt
newline

重定向标准 I/O

有时需要把文件内容做为输入,或把错误信息输出到文件。

重定向输出

有两种重定向输出的方法:

  • n> 从描述符 n 重定向到文件

必须对文件有写权限,如果文件不存在,会自动创建;如果存在,文件内容会被覆盖,没有提醒。

  • n>> 从描述符 n 重定向到文件

必须对文件有写权限,如果文件不存在,会自动创建;如果存在,文件内容会被追加到末尾。

简写

如果描述符 n 被省略,默认代表标准输出。

> = 1>

>> = 1>>

合并重定向

有时需要把标准 输出 和标准 错误 重定向到 同一个文件 中,常用于自动化处理,或后台工作。

  • 方法 1:&>&>>

这种方法直接把输出和错误同时重定向。

  • 方法 2: >output.txt 2>&1

先指定标准输出的重定向,再把标准错误重定向到标准输出的位置。于是二者被合并到一起。

顺序很重要,假设当前标准输出的位置为显示器,则 2>&1 >output.txt 的结果是错误被输出到显示器,而标准输出被保存到文件。

忽略输出

有时需要忽略标准输出或标准错误,可以将其重定向到 /dev/null

范例

  • 把标准错误定向到文件

2>2>>

  • 将标准输出和标准错误重定向到同一位置

&>&>>

command >output.txt 2>&1

  • 把标准输出,标准错误分别重定向

command >stdout.txt 2>stderr.txt

command >>stdout.txt 2>>stderr.txt

command 2>&1 >output.txt

ll aaa sss 2>/dev/null

重定向输入

< 可以把标准输入重定向到某个文件。

Here-Document

Here Document 是输入重定向的一种形式,<< 关键字,该关键字将成为本次输入的 结束标志。于是在这一对标志之间的文本成为本次输入的内容。

经常用在脚本中,这是在脚本中指定多行输入内容的唯一的方法。

#!/bin/bash
cat <<EOF>log.​txt
LOG FILE HEADER
This is a test log file
Function: System statistics
EOF

如果使用 <<- 关键字,则每一行输入 开头的 tab 会被删掉

范例

  • 重定向输入到文件

tr ' ' '\t'<text1

  • 使用 here-document

sort -k2 <<END

  • 复制指定文件内容到新文件

cat > catfile < ~/.bashrc

  • 使用交互式环境新建文件

cat > catfile

  • 使用 here-document 方式新建文件

cat > catfile <<"eof"