在命令行界面中,程序通常与三种标准数据流打交道:
stdin):程序接收输入的地方(通常来自键盘)。stdout):程序发送正常输出的地方(通常输出到终端屏幕)。stderr):程序发送错误消息的地方(通常输出到终端屏幕)。我们在管道与命令列表一章中介绍过这些内容。
管道可以看作是重定向的一种形式:一个程序的标准输出直接发送到另一个程序的标准输入。 我们已经介绍过管道。 本节将介绍如何在文件和标准流之间进行重定向。
Shell 重定向是一种强大的机制,可以改变这些数据流的去向。 你可以让程序不再从键盘读取、不再向屏幕输出,而是从文件重定向输入,或者把输出发送到文件。 这样,你就能非常灵活地控制程序与数据交互的方式。
下面是最常见的重定向运算符及其作用:
>(输出重定向)用途:把命令的标准输出(stdout)重定向到文件。
行为:
示例:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
重定向是在命令执行之前完成的。 这意味着你不能把输出重定向到同一个需要读取的文件。
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
在上面的第二个命令中,
>>(追加输出重定向)用途:把命令的标准输出(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
在 shell 编程以及 Linux/Unix 这类操作系统中,文件描述符(FD)是一个非负整数,用来标识或引用一个打开的文件或 I/O(输入/输出)资源。 你可以把它想象成操作系统用来跟踪打开的文件和数据流的标签或引用编号。
你在重定向左侧看到的数字就是文件描述符。
标准 I/O 流会分配到前 3 个文件描述符:
可以用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 重定向让你能精细地控制程序与数据交互的方式,从而构建复杂的工作流并高效地管理信息。