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

文件描述符重定向

每个打开的文件都会被分配一个文件描述符stdinstdoutstderr的文件描述符分别是012。对于打开的额外文件,保留描述符39

## 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

参考资料

最后更新于