I/O重定向
I/O 重定向
在UNIX系统中,获取输入和写入输出的流是预定义的。总是有三个默认文件打开:
stdin
是输入数据源(键盘)stdout
是输出数据源(屏幕)stderr
是标准错误输出源(错误消息输出到屏幕)
这些以及任何其他打开的文件都可以被重定向。重定向简单地说就是捕获来自文件、命令、程序、脚本甚至脚本内代码块的输出,并将其作为输入发送到另一个文件、命令、程序或脚本。
基本重定向操作
## command_output >
# 将stdout重定向到文件
# 如果文件不存在则创建,否则覆盖它
$ ls -la > ls_result.txt
## : > filename
# '>' 将文件 'filename' 截断为零长度
# 如果文件不存在,创建零长度文件(与 'touch' 效果相同)
# ':' 用作虚拟占位符,不产生输出
$ : > empty_file.txt
## command_output >>
# 将stdout重定向到文件
# 如果文件不存在则创建,否则追加到它
$ ls -la >> ls_result.txt
文件描述符重定向
每个打开的文件都会被分配一个文件描述符。stdin
、stdout
和stderr
的文件描述符分别是0
、1
和2
。对于打开的额外文件,保留描述符3
到9
。
## 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
高级重定向技巧
合并输出流
# 将stderr重定向到stdout
$ command 2>&1
# 将stdout和stderr都重定向到文件
$ command &> output.txt
$ command > output.txt 2>&1
# 将stdout重定向到文件,stderr重定向到另一个文件
$ command > stdout.txt 2> stderr.txt
输入重定向
# 从文件读取输入
$ command < input.txt
# 从here document读取输入
$ command << EOF
line1
line2
EOF
# 从here string读取输入
$ command <<< "hello world"
进程替换
# 将命令的输出作为文件使用
$ diff <(command1) <(command2)
# 将多个命令的输出合并
$ cat <(ls) <(pwd)
防止意外覆盖
你可以通过在shell中设置noclobber
选项来确保没有任何重定向会破坏现有文件:
$ set -o noclobber
$ sort file.txt > file.txt
-bash: file.txt: cannot overwrite existing file
# 临时覆盖
$ sort file.txt >| file.txt
# 关闭noclobber
$ set +o noclobber
实用示例
日志记录
# 将正常输出和错误分别记录到不同文件
$ ./script.sh > success.log 2> error.log
# 将所有输出记录到同一文件
$ ./script.sh > all.log 2>&1
# 同时输出到屏幕和文件
$ ./script.sh 2>&1 | tee output.log
调试
# 仅显示错误
$ ./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 - 深入了解UNIX工作原理
Advanced Bash-Scripting Guide: I/O Redirection - 高级Bash脚本编写指南
Bash Redirections Cheat Sheet - Bash重定向速查表
最后更新于