重定向和管道
标准输入和输出:
程序:指令+数据
读入数据:Input
输出数据:Output
打开的文件都有一个fd: file descriptor (文件描述符)
Linux给程序提供三种I/O设备
- 标准输入(STDIN)-0默认接受来自键盘的输入
- 标准输出(STDOUT)-1默认输出到终端窗口
- 标准错误(STDERR)-2默认输出到终端窗口
I/O重定向:改变默认位置
[root@localhost /app]#ls >/dev/pts/7
本终端窗口不进行输出,将结果输出到别的终端窗口。
把输出和错误重新定向到文件:
STDOUT和STDERR可以被重定向到文件
命令 操作符号 文件名
支持的操作符号包括:
> 把STDOUT重定向到文件
2>把STDERR重定向到文件
&>把所有输出重定向到文件
> 文件内容会被覆盖
set –C 禁止将内容覆盖已有文件,但可追加
>| file 强制覆盖
set +C 允许覆盖
>> 原有内容基础上,追加内容,原文件存在不刷新时间戳。
2>覆盖重定向错误输出数据流
2>>追加重定向错误输出数据流
标准输出和错误输出各自定向至不同位置
COMMAND > /path/to/file.out2> /path/to/error.out
合并标准输出和错误输出为同一个数据流进行重定向
&>覆盖重定向
&>> 追加重定向
COMMAND > /path/to/file.out2>&1 (顺序很重要)
COMMAND >> /path/to/file.out2>&1
():合并多个程序的STDOUT
(cal2007;cal2008)> all.txt
[root@localhost /app]#(hostname;whoami;ls)>a.txt
[root@localhost /app]#cat a.txt
localhost.localdomain
root
a
aaaa
f
lost+found
加上( )把三个命令的结果全部添加到文件a.txt中。如果不加( )由于优先级问题就会先执行>即a.txt中的内容为ls执行的结果。
[root@localhost /app]#(error;hostname)>aaa.log 2>&1
把错误的重定向到标准输出,而标准输出是放到aaa.log文件中的。
[root@localhost /app]#(error;hostname) 2>&1 >a
-bash: error: command not found
2>&1放前面和后面是完全不一样的结果,前一条命令直接变成对的输出到屏幕,后一条命令是对的直接输出到文件。
[root@localhost /app]#((error;hostname) 2>&1) >a
[root@localhost /app]#cat a
-bash: error: command not found
localhost.localdomain
这样加上( )经过转换就可以了。
[root@localhost /app]#(error;hostname)&>aaa.log
等价于上一条执行的命令。
[root@localhost /app]#ls >/dev/null
/dev/null是黑洞设备,不需要输出到窗口的信息可以重定向到这里。
[root@localhost /app]#(echo error 1>&2) > /dev/null
error
把对的转化为错的,显示的结果不能标准输出到/dev/null中
tr命令:
tr转换和删除字符
tr[OPTION]... SET1 [SET2]
选项:
-c–C --complement:取字符集的补集
-d--delete:删除所有属于第一字符集的字符
-s--squeeze-repeats:把连续重复的字符以单独一个字符表示
-t--truncate-set1:将第一个字符集对应字符转化为第二字符集
对应的字符
[:alnum:]:字母和数字 [:alpha:]:字母[:cntrl:]:控制(非打印)字符[:digit:]:数字 [:graph:]:图形字符 [:lower:]:小写字母[:print:]:可打印字符 [:punct:]:标点符号 [:space:]:空白字符 [:upper:]:大写字母 [:xdigit:]:十六进制字符
从文件中导入STDIN:
使用<来重定向标准输入
某些命令能够接受从文件中导入的STDIN
tr‘a-z’‘A-Z’</etc/issue
该命令会把/etc/issue中的小写字符都转换成大写字符
tr –d abc < /etc/fstab 删除fstab文件中的所有abc中任意字符
cat > file
sunan
sunanblog.com
按ctrl+d离开,可以使用文件来代替键盘的输入
cat > filea <fileb
[root@localhost /app]#tr 123 ab
123456123
abb456abb
3没有代替的直接用b代替。
[root@localhost /app]#tr -t 123 ab
12345123456
ab345ab3456
-t选项是截断,相当于3不要了。
[root@localhost /app]#tr -d 'a-z'<fstab
# A , , '//'
# S (5), (8), (8) / (8)
#
UUID=044064-970-41-9-74526493 / 4 1 1
UUID=859743-0-49-26-803582 / 4 1 2
UUID=0759--4156-25-23245 / 4 1 2
UUID=435474-0-47-459-152686446 0 0
......
将文件中的小写字母全部删掉。
[root@localhost /app]#tr -d 'a-z'<fstab >fstab2
[root@localhost /app]#cat fstab2
#
......
UUID=044064-970-41-9-74526493 / 4 1 1
UUID=859743-0-49-26-803582 / 4 1 2
UUID=0759--4156-25-23245 / 4 1 2
UUID=435474-0-47-459-152686446 0 0
......
转化过后重定向到新的文件中。
[root@localhost /app]#tr -d 'a-z'<fstab >fstab
上面的命令执行会把fstab文件中的内容清空,在单一命令中,一次只能处理一次,打开的同时再重定向是不行的,只能换一个新的文件名。
[root@localhost /app]#tr -s 'a'
asdfaaaaasdfsdfsaaaa
asdfasdfsdfsa
-s是将重复的a进行压缩。
[root@localhost /app]#tr -dc 'a'
asdfvdssd
sdfas
sdfasdf
这条命令按回车是不会执行的,因为-c是取a的补集,-d是删除,即除了a意思是包括\n回车也会当成输入来执行,只能按Ctrl+d进行处理。
[root@localhost /app]#tr -dc 'a\n '
asdfsdfaaa
aaaa
这样加上回车换行\n就可以了。
[root@localhost /app]#cat win.txt
a
b
c[root@localhost /app]#
查看windows上传的win.txt文件
[root@localhost /app]#hexdump -C win.txt
00000000 61 0d 0a 62 0d 0a 63 |a..b..c|
00000007
查看windows上传的文件的16进制编码
[root@localhost /app]#cat linux.txt
a
b
c
[root@localhost /app]#
查看linux上的文件linux.txt,内容是一样的。l
[root@localhost /app]#hexdump -C linux.txt
00000000 61 0a 62 0a 63 0a |a.b.c.|
00000006
查看Linux上的文件和Windows上传文件内容一样。但inux上以前为了节省空间,把回车和换行用一个换行表示,windows上回车是回车换行是换行。
[root@localhost /app]#tr -d '\r' <win.txt >newwin.txt
[root@localhost /app]#hexdump -C newwin.txt
00000000 61 0a 62 0a 63 |a.b.c|
00000005
这条命令就把windows文件转换为linux文件了,说明windows中的文件和linux中的文件是不同的。
[root@localhost /app]#hexdump -c linux.txt
0000000 a \n b \n c \n
0000006
[root@localhost /app]#hexdump -c win.txt
0000000 a \r \n b \r \n c
0000007
加小c选项可以直接看到回车和换行。
[root@localhost /app]#dos2unix win.txt
dos2unix: converting file win.txt to UNIX format ...
[root@localhost /app]#hexdump -c win.txt
0000000 a \n b \n c
0000005
使用dos2unix可以直接windows文件格式直接转换linux文件格式,当然,unix2dos是转换回去。
[root@localhost /app]#cat aa
aaa
bbb
ccc
[root@localhost /app]#tr '\n' '\t' <aa
aaa bbb ccc [root@localhost /app]#
[root@localhost /app]#
[root@localhost /app]#tr '\n' '\v' <aa
aaa
bbb
ccc
[root@localhost /app]#
将文件中的换行替换成水平tab键(水平制表符)和垂直tab键(垂直制表符)
把多行发送给STDIN:
使用“<<终止词”命令从键盘把多行重导向给STDIN
直到终止词位置的所有文本都发送给STDIN
有时被称为就地文本(heretext)
mail -s "PleaseCall" root<<END
>HiSun,
>
>Pleasegivemeacallwhenyougetin.Wemayneed
>todosomemaintenanceonserver1.
>
>Detailswhenyou'reon-site
>sun
>END
向root发送邮件
[root@localhost ~]#>/var/spool/mail/root
清空邮件。
[root@centos6 /]#mail -s "hello" root <<END
asddf
END
[root@centos6 /]#send-mail: warning: valid_hostname: numeric hostname: 9
send-mail: fatal: file /etc/postfix/main.cf: parameter mydomain: bad parameter value: 9
mai发送各种失败,不知道为什么,只能网上搜索答案。
[root@localhost ~]#hostnamectl set-hostname localhost
需要上面这条命令,然后重启机器就好了,网上答案说单机模式主机名需要改为localhost,至于为什么再做研究。
管道:
管道(使用符号“|”表示)用来连接命令
命令1 | 命令2 | 命令3 | …
将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
STDERR默认不能通过管道转发,可利用2>&1 或|& 实现
最后一个命令会在当前shell进程的子shell进程中执行用来
组合多种工具的功能
ls | tr 'a-z' 'A-Z'
less :一页一页地查看输入
ls-l/etc|less
mail:通过电子邮件发送输入
echo"testemail"|mail-s "test"user@example.com
lpr:把输入发送给打印机
echo"testprint"|lpr-Pprinter_name
管道中的 – 符号
示例:
将/home 里面的文件打包,但打包的数据不是记录到文件,而是传送到stdout,经过管道后,将tar -cvf-/home 传送给后面的tar -xvf-, 后面的这个-则是取前一个命令的stdout,因此,就不需要使用临时file了
tar -cvf-/home | tar -xvf-
重定向到多个目标:
命令1 | tee[-a ] 文件名| 命令2
把命令1的STDOUT保存在文件中,做为命令2的输入 -a 追加
使用:
保存不同阶段的输出
复杂管道的故障排除
同时查看和记录输出
[root@localhost /app]#ls |tee ls.out
lost+found
newwin.txt
win.txt
win..txt
[root@localhost /app]#cat ls.out
lost+found
newwin.txt
win.txt
win..txt
既想在屏幕输出又想保存到文件可以用tee命令
[root@localhost /app]#pwd |tee -a ls.out
/app
[root@localhost /app]#cat ls.out
lost+found
newwin.txt
win.txt
win..txt
/app
-a(append)选项是将新生成的内容追加到文件中。