Linux重定向
程序:指令+数据
读入数据: Input
输出数据: Output
打开的文件都有一个fd: file descriptor (文件描述符)
Linux给程序提供三种I/O设备
标准输入( STDIN) 0 默认接受来自键盘的输入
标准输出( STDOUT) 1 默认输出到终端窗口
标准错误( STDERR) 2 默认输出到终端窗口
[root@localhost /testdir]# ll /dev/std*
lrwxrwxrwx. 1 root root 15 Aug 28 22:22 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root 15 Aug 28 22:22 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 Aug 28 22:22 /dev/stdout -> /proc/self/fd/1
I/O重定向:改变默认位置
STDOUT和STDERR可以被重定向到文件:
命令 操作符号 文件名
支持的操作符号包括:
> 把STDOUT重定向到文件
2> 把STDERR重定向到文件
&> 把所有输出重定向到文件
> 文件内容会被覆盖
# set -C: 禁止将内容覆盖已有文件,但可追加
强制覆盖: >|
# set +C: 允许覆盖
>> 原有内容基础上,追加内容
2>: 覆盖重定向错误输出数据流;
2>>: 追加重定向错误输出数据流;
标准输出和错误输出各自定向至不同位置:
COMMAND > /path/to/file.out 2> /path/to/error.out
合并标准输出和错误输出为同一个数据流进行重定向:
&>:覆盖重定向
&>>:追加重定向
COMMAND > /path/to/file.out 2> &1 (顺序很重要)
COMMAND >> /path/to/file.out 2>> &1
find /etc -name passwd 2> /dev/null
():合并多个程序的STDOUT
[root@localhost /testdir]# (cal 2016;cal 2017) > cal.txt #将两个命令的结果输出到cal.txt文件中
[root@localhost /testdir]# (date; lsdf) &> all.txt #将标准输出和错误输出全部写入到all.txt文件中
[root@localhost /testdir]# cat all.txt
Mon Aug 29 20:04:27 CST 2016
bash: lsdf: command not found...
注意:
1、shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空。
2、“>>”操作符,判断右边文件,如果不存在,先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1,2]然后,与左边的标准输出(1)或错误输出(2) 绑定。
3、当命令执行完,绑定文件的描述符也自动失效。0,1,2又会空闲。
4、一条命令启动,命令的输入,正确输出,错误输出,默认分别绑定0,1,2文件描述符。
5、一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行
示例:
[root@localhost /testdir]# set -C bs #禁止将内容覆盖已有文件
[root@localhost /testdir]# echo "nnnnnnnnnn" > bs
-bash: bs: cannot overwrite existing file
[root@localhost /testdir]# echo "mmmmmmmmm" >| bs
[root@localhost /testdir]# echo "nnnnnnnn" >> bs
[root@localhost /testdir]# cat bs
mmmmmmmmm
nnnnnnnn
[root@localhost /testdir]# set +C bs #允许覆盖
[root@localhost /testdir]# echo "aaaaaaaa" > bs
[root@localhost /testdir]# echo "Hello World" > wel #覆盖写入
[root@localhost /testdir]# echo "Hello" >> wel #追加写入
[root@localhost /testdir]# cat wel
Hello World
Hello
[root@localhost /testdir]# cat < /etc/issue #从指定文件读取内容
\S
Kernel \r on an \m
[root@localhost /testdir]# lsdfdf &> err.txt #不管是标准输出还是错误输出都写入到err.txt文件中
[root@localhost /testdir]# cat err.txt
bash: lsdfdf: command not found...
从文件中导入STDIN
使用 < 来重定向标准输入
某些命令能够接受从文件中导入的STDIN:
把/etc/issue中的小写字符都转换成写写字符
[root@localhost /testdir]# tr 'a-z' 'A-Z' < /etc/issue
\S
KERNEL \R ON AN \M
删除issue文件中的指定的字符
[root@localhost /testdir]# tr -d 'a-h' < /etc/issue
\S
Krnl \r on n \m
[root@localhost /testdir]# cat > t < test
[root@localhost /testdir]# cat t
1212121
[root@localhost /testdir]# cat test
1212121
把多行发送给STDIN
使用“ <<终止词”命令从键盘把多行重导向给STDIN
直到 终止词 位置的所有文本都发送给STDIN
有时被称为就地文本( heretext)
[root@localhost /testdir]# cat > file <
> hello
> world
> hi,
> end
[root@localhost /testdir]# cat file
hello
world
hi,
管道
管道(使用符号“ |”表示)用来连接命令
命令1 | 命令2 | 命令3 | …
将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
STDERR默认不能通过管道转发,可利用2>&1 或 |& 实现
最后一个命令会在当前shell进程的子shell进程中执行用来
组合多种工具的功能
[root@localhost /testdir]# ls
all.txt cal.txt err.txt file
[root@localhost /testdir]# ls | tr 'a-z' 'A-Z'
ALL.TXT
CAL.TXT
ERR.TXT
FILE
less :一页一页地查看输入:
[root@localhost /testdir]# ls -l /etc/ | less#分页显示/etc目录下的列表
mail: 通过电子邮件发送输入:
[root@localhost /testdir]# echo "test mail" | mail -s test root#给root发送邮件
lpr:把输入发送给打印机
[root@localhost /testdir]# echo "test print" | lpr -P printer
重定向到多个目标( tee)
命令1 | tee 文件名 | 命令2
把命令1的STDOUT保存在文件名中,然后管道输入给命令2
使用:
保存不同阶段的输出
复杂管道的故障排除
同时查看和记录输出
[root@localhost /testdir]# ls | tee sc.txt | tr 'a-z' 'A-Z'
ALL.TXT
CAL.TXT
ERR.TXT
FILE
[root@localhost /testdir]# cat sc.txt
all.txt
cal.txt
err.txt
file