第五章 linux重定向和管道

时间:2022-03-07 15:09:30

重定向和管道

标准输入和输出:

程序:指令+数据

读入数据: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)选项是将新生成的内容追加到文件中。