重定

重定向 属于 Bash

{other: "%{count} 个练习"}

关于 重定向

在命令行界面中,程序通常与三种标准数据流打交道:

  1. 标准输入(stdin):程序接收输入的地方(通常来自键盘)。
  2. 标准输出(stdout):程序发送正常输出的地方(通常输出到终端屏幕)。
  3. 标准错误(stderr):程序发送错误消息的地方(通常输出到终端屏幕)。

我们在管道与命令列表一章中介绍过这些内容。

Note

管道可以看作是重定向的一种形式:一个程序的标准输出直接发送到另一个程序的标准输入。 我们已经介绍过管道。 本节将介绍如何在文件和标准流之间进行重定向。

Shell 重定向是一种强大的机制,可以改变这些数据流的去向。 你可以让程序不再从键盘读取、不再向屏幕输出,而是从文件重定向输入,或者把输出发送到文件。 这样,你就能非常灵活地控制程序与数据交互的方式。

常用的重定向运算符

下面是最常见的重定向运算符及其作用:

>(输出重定向)

  • 用途:把命令的标准输出(stdout)重定向到文件。

  • 行为:

    • 如果文件不存在,就创建它。
    • 如果文件已存在,就覆盖它的内容。
  • 示例:

    # Sends the output of 'ls -l' to 'file_listing.txt'
    ls -l > file_listing.txt
    
Caution

重定向是在命令执行之前完成的。 这意味着你不能把输出重定向到同一个需要读取的文件。

date > date.txt         # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!

在上面的第二个命令中,

  1. Bash 先截断重定向中指定的文件。 这会破坏原有内容,留下一个空文件。
  2. 然后 bash 读取这个刚变成空的文件。
  3. 然后 bash 把内容(也就是什么都没有)写回文件。

>>(追加输出重定向)

  • 用途:把命令的标准输出(stdout)追加到文件。

  • 行为:

    • 如果文件不存在,就创建它。
    • 如果文件已存在,输出会添加到文件的末尾。
  • 示例:

    # Adds "Another line" to the end of the file
    echo "Another line" >> file_listing.txt
    

<(输入重定向)

  • 用途:从文件重定向命令的标准输入(stdin)。

  • 行为:命令从指定的文件读取输入,而不是从键盘读取。

  • 示例:

    # 'tr' reads from 'lowercase.txt' and
    # output is redirected to 'uppercase.txt'
    tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
    

2>(错误重定向):

  • 用途:把命令的标准错误(stderr)重定向到文件。
  • 行为:错误消息会发送到指定的文件,而不是终端。
  • 示例:
    # Error message from 'rm' is sent to 'error_log.txt'
    rm non_existent_file 2> error_log.txt
    

你可以用 2>> 把标准错误_追加_到文件中。

其他重定向

还有一些重定向可以合并 stdin 和 stderr。 详情请参阅手册。

/dev/null

/dev/null 是一个特殊的文件,它

  • 在你读取时是一个空文件,并且
  • 会丢弃所有写入它的数据。

它有时被称为“bitbucket”。 它适合用来屏蔽输出或错误。

some_command > /dev/null  # Discards stdout
some_command 2> /dev/null # Discards stderr

# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null

组合重定向

可以一次给出多个重定向。

some_command < input.txt > output.txt 2> error.txt

重定向可以被复制。

# send stderr to the same destination as stdout
some_command > output.txt 2>&1

看到2>&1时,把它读作“把 stderr 重定向到 stdout 当前指向的地方”。 Bash 严格按从左到右的顺序处理重定向指令,也就是说你可以这样做:

# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
Advanced

文件描述符

在 shell 编程以及 Linux/Unix 这类操作系统中,文件描述符(FD)是一个非负整数,用来标识或引用一个打开的文件或 I/O(输入/输出)资源。 你可以把它想象成操作系统用来跟踪打开的文件和数据流的标签或引用编号。

你在重定向左侧看到的数字就是文件描述符。

标准 I/O 流会分配到前 3 个文件描述符:

  • 标准输入是 FD 0
  • 标准输出是 FD 1
  • 标准错误是 FD 2

可以用exec命令和重定向运算符设置或创建新的文件描述符。

# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt

# then redirect both stdout and file descriptor 3
echo "some debug message" >&3  # displayed in the terminal
some_command  2>&1 # stdout and stderr send to 'log.txt'

这种技巧看起来相当绕,但在脚本由其他软件包运行、标准输出会被该软件自动捕获的情况下,它非常有用。 本学习轨道用来运行单元测试的bats命令就是这样工作的:bats会捕获测试的 stdout 和 stderr,但发送到 FD 3 的调试消息会显示在终端上。

小结

重定向有什么用?

  • 保存输出:把命令的结果保存下来,以便之后查看或处理。
  • 记录日志:捕获错误消息,方便调试。
  • 自动化:把命令串联起来,用一个命令的输出作为另一个命令的输入。
  • 过滤:丢弃不需要的输出。
  • 批量处理:处理来自文件的数据,而不用手动输入。
  • 编写脚本:重定向是编写健壮 shell 脚本的基础。

Shell 重定向让你能精细地控制程序与数据交互的方式,从而构建复杂的工作流并高效地管理信息。

通过 GitHub 编辑 该链接会在新窗口或标签页中打开