标准I/O重定向和管道
程序:
指令+数据
读入数据:Input
输出数据:Onutput
打开文件都有一个fd: file descriptor(文件描述符)
[root@centos8 ~]# ll /dev/std* “/dev/stdin、/dev/stdout、/dev/stderr它们分别是各个终端字符设备的软链接”
lrwxrwxrwx. 1 root root 15 Mar 26 17:11 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root 15 Mar 26 17:11 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 Mar 26 17:11 /dev/stdout -> /proc/self/fd/1
[root@centos8 ~]#
[root@centos8 ~]# ll /proc/self/fd/*
ls: cannot access '/proc/self/fd/255': No such file or directory
lrwx------. 1 root root 64 Mar 26 17:56 /proc/self/fd/0 -> /dev/pts/0
lrwx------. 1 root root 64 Mar 26 17:56 /proc/self/fd/1 -> /dev/pts/0
lrwx------. 1 root root 64 Mar 26 17:56 /proc/self/fd/2 -> /dev/pts/0
lr-x------. 1 root root 64 Mar 26 17:56 /proc/self/fd/3 -> /var/lib/sss/mc/passwd
lrwx------. 1 root root 64 Mar 26 17:56 /proc/self/fd/4 -> 'socket:[53663]'
lr-x------. 1 root root 64 Mar 26 17:56 /proc/self/fd/5 -> /var/lib/sss/mc/group
[root@centos8 ~]#
[root@centos8 ~]# ll /proc/`pidof tail` /fd
ls: cannot access '/fd': No such file or directory
/proc/:
total 0
dr-xr-xr-x. 9 root root 0 Mar 26 17:11 1
dr-xr-xr-x. 9 root root 0 Mar 26 17:11 10
dr-xr-xr-x. 9 gdm gdm 0 Mar 26 17:11 1017
dr-xr-xr-x. 9 gdm gdm 0 Mar 26 17:11 1046
dr-xr-xr-x. 9 gdm gdm 0 Mar 26 17:11 1079
dr-xr-xr-x. 9 gdm gdm 0 Mar 26 17:11 1080
dr-xr-xr-x. 9 root root 0 Mar 26 17:11 11
dr-xr-xr-x. 9 gdm gdm 0 Mar 26 17:11 1103
dr-xr-xr-x. 9 gdm gdm 0 Mar 26 17:11 1129
dr-xr-xr-x. 9 root root 0 Mar 26 17:11 114
dr-xr-xr-x. 9 root root 0 Mar 26 17:11 115
dr-xr-xr-x. 9 root root 0 Mar 26 17:11 116
Linux给程序提供三种I/O设备
标准输入(STDIN)-0 默认接受来自键盘的输入
标准输出(STDOUT)-1 默认输出到终端窗口
标准错误(STDERR)-2 默认输出到终端窗口
I/O重定向:
将默认的输入,输出或错误对应的设备改变,指向新的目标。
标准输出和标准错误可以被重定向到文件
STDOUT和STDERR可以被重定向到指定文件,而非默认的当前终端
格式:
命令 操作符号 文件名
支持的操作符号包括:
> :把标准输出(stdout)重定向到文件,会覆盖原文件内容
>> :把标准输出(stdout)重定向到文件,会在原有内容基础上,追加内容
2> :把标准错误(stderr)重定向到文件,会覆盖原内容
2>>:把标准错误(stderr)重定向到文件,会在原内容基础上,追加内容
&>:把所有的输出重定向到文件,不管对错都输出到指定位置,覆盖输出
&>>:把所有的输出重定向到文件,不管对错都输出到指定位置,追加输出
2>&1和&>,&>>效果一样,2>&1是老版本使用,要在最后使用,才有效果。
command >/path/toshmefile 2>&1
command>>/path/to/somefile 2>&1
理解:A和B,将A输出到B上,如果对了,就正常输出到B上,如果错误了,内容还是输出在B上
合并多个程序的标准输出:
(command ;command)>file
特例:将ll和echo shell的标准输出一起重定向到file文件中,此法只能用于标准输出,
标准错误不能使用
范例:
[root@centos8 ~]# (ll /root ; echo hello) > /data/file.txt
[root@centos8 ~]# cat /data/file.txt
total 12
-rw-------. 1 root root 1594 Mar 16 18:55 anaconda-ks.cfg
-rw-------. 1 root root 1866 Mar 26 17:28 dead.letter
-rw-r--r--. 1 root root 1749 Mar 16 19:01 initial-setup-ks.cfg
hello
[root@centos8 ~]#
范例:标准错误重定向
[root@centos8 ~]# touch /data/f1.log
[root@centos8 ~]# touch /data/all.log
[root@centos8 ~]# rm /data/f1.log 2>/data/all.log
[root@centos8 ~]# cd /data/all.log
-bash: cd: /data/all.log: Not a directory
[root@centos8 ~]# cat /data/all.log
rm: remove regular empty file '/data/f1.log'?
[root@centos8 ~]# y
范例:合并多个命令的结果至一个文件中
[root@centos8 ~]# ( cal 2019 ; cal 2020) > all.txt
[root@centos8 ~]# cat all.txt
2019
January February March
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 1 2 1 2
6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9
13 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16
20 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23
27 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30
31
2020
January February March
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 1 1 2 3 4 5 6 7
5 6 7 8 9 10 11 2 3 4 5 6 7 8 8 9 10 11 12 13 14
12 13 14 15 16 17 18 9 10 11 12 13 14 15 15 16 17 18 19 20 21
19 20 21 22 23 24 25 16 17 18 19 20 21 22 22 23 24 25 26 27 28
26 27 28 29 30 31 23 24 25 26 27 28 29 29 30 31
[root@centos8 ~]# { ls ; hostname ;} > /data/all.log
[root@centos8 ~]# cat /data/all.log
all.txt
anaconda-ks.cfg
dead.letter
initial-setup-ks.cfg
centos8.magedu.org
[root@centos8 ~]#
范例:清除大文件
cat /dev/null > /data/file.log
范例:分别重定向
[root@centos8 ~]# ls /data/ /xxx > stdout.log 2>stderr.log
范例:将标准输出和错误都重定向到同一个文件
[root@centos8 ~]# ls /data /xxx > /data/all.log 2>&1
[root@centos8 ~]# ls /data /xxx 2> /data/all.log 1>&2
[root@centos8 ~]# ls /data /xxx &> /data/all.log
[root@centos8 ~]# ls /data /xxx 2>&1 /data/all.log
ls: cannot access '/xxx': No such file or directory
范例:
[root@centos8 ~]# ll /root > /data/file.txt
[root@centos8 ~]# cat /data/file.txt
total 12
-rw-------. 1 root root 1594 Mar 16 18:55 anaconda-ks.cfg
-rw-------. 1 root root 1866 Mar 26 17:28 dead.letter
-rw-r--r--. 1 root root 1749 Mar 16 19:01 initial-setup-ks.cfg
[root@centos8 ~]#
[root@centos8 ~]# ll /etc >> /data/file.txt
[root@centos8 ~]# cat /data/file.txt
total 12
-rw-------. 1 root root 1594 Mar 16 18:55 anaconda-ks.cfg
-rw-------. 1 root root 1866 Mar 26 17:28 dead.letter
-rw-r--r--. 1 root root 1749 Mar 16 19:01 initial-setup-ks.cfg
total 1360
-rw-r--r--. 1 root root 16 Mar 16 18:54 adjtime
-rw-r--r--. 1 root root 1518 Sep 10 2018 aliases
drwxr-xr-x. 3 root root 65 Mar 16 18:52 alsa
drwxr-xr-x. 2 root root 4096 Mar 16 18:53 alternatives
-rw-r--r--. 1 root root 541 May 11 2019 anacrontab
-rw-r--r--. 1 root root 55 May 14 2019 asound.conf
-rw-r--r--. 1 root root 1 May 11 2019 at.deny
讲ll显示的结果输出重定向到文件file中,使用>时,file文件被覆盖了,使用>>时,原文件file和重定向的内容都显示了,是追加内容。
tr命令
-
tr :转换和删除字符
-
tr [OPTION]… SET1 [SET2] ( []非必选)
-
常用选项:
① -c –C –-complement:取字符集的补集
② -d –-delete:删除所有属于第一字符集的字符
③ -s –-squeeze-repeats:把连续重复的字符以单独一个字符表示
④ -t –-truncate-set1:将第一个字符集对应字符转化为第二字符集对应的字符[:alnum:]:字母和数字 [:alpha:]:字母 [:digit:]:数字 [:lower:]:小写字母 [:upper:]:大写字母 [:space:]:空白字符 [:print:]:可打印字符 [:punct:]:标点字符 [:graph:]:图形字符 [:cntrl:]:控制(非打印)字符 [:xdigit:]:十六进制字符
范例:
“该命令会把/etc/issue中的小写字符转化为大写字符” [root@centos8 ~]# tr 'a-z' 'A-Z' </etc/issue “删除fstab文件中的所有ABC中任意字符” [root@centos8 ~]# tr -d abc < /etc/fstab
范例:取消空格符
[root@centos8 ~]# df Filesystem 1K-blocks Used Available Use% Mounted on devtmpfs 992100 0 992100 0% /dev tmpfs 1006652 0 1006652 0% /dev/shm tmpfs 1006652 9524 997128 1% /run tmpfs 1006652 0 1006652 0% /sys/fs/cgroup /dev/sda2 104806400 5510208 99296192 6% / /dev/sda3 52403200 398584 52004616 1% /data /dev/sda1 999320 116032 814476 13% /boot tmpfs 201328 16 201312 1% /run/user/42 tmpfs 201328 4 201324 1% /run/user/0 [root@centos8 ~]# df >df.log [root@centos8 ~]# tr -s ' ' : < df.log Filesystem:1K-blocks:Used:Available:Use%:Mounted:on devtmpfs:992100:0:992100:0%:/dev tmpfs:1006652:0:1006652:0%:/dev/shm tmpfs:1006652:9524:997128:1%:/run tmpfs:1006652:0:1006652:0%:/sys/fs/cgroup /dev/sda2:104806400:5510208:99296192:6%:/ /dev/sda3:52403200:398584:52004616:1%:/data /dev/sda1:999320:116032:814476:13%:/boot tmpfs:201328:16:201312:1%:/run/user/42 tmpfs:201328:4:201324:1%:/run/user/0 [root@centos8 ~]#
范例:将Windows的文本转化为Linux的文本格式
[root@centos8 ~]# cat windows.txt a b c[root@centos8 ~]# file windows.txt windows.txt: ASCII text, with CRLF line terminators [root@centos8 ~]# hexdump -C windows.txt 00000000 61 0d 0a 62 0d 0a 63 |a..b..c| 00000007 [root@centos8 ~]# nano linux.txt [root@centos8 ~]# hexdump -C linux.txt 00000000 61 20 62 20 63 0a |a b c.| 00000006 [root@centos8 ~]# tr -d '\r' < windows.txt > windows2.txt [root@centos8 ~]# ls all.txt dead.letter initial-setup-ks.cfg stderr.log windows2.txt anaconda-ks.cfg df.log linux.txt stdout.log windows.txt [root@centos8 ~]# hexdump -C windows2.txt 00000000 61 0a 62 0a 63 |a.b.c| 00000005 [root@centos8 ~]# file windows2.txt windows2.txt: ASCII text
标准输入重定向
- 利用“<”可以将标准输入重定向
范例:
[root@centos8 ~]# echo 2^3 >bc.log
[root@centos8 ~]# cat bc.log
2^3
[root@centos8 ~]# bc < bc.log
8
[root@centos8 ~]#
-
cat > file
cat > file hello world #按ctrl+d离开,可以使用文件来代替键盘的输入 [root@centos8 ~]# cat > cat.log asdas da asda asd ^C [root@centos8 ~]# cat cat.log asdas da asda
-
Cat > filea < fileb
-
cat < file1 >> file1
[root@centos8 ~]# cat < mail.txt hello how old you [root@centos8 ~]# cat mail.txt hello how old you [root@centos8 ~]# cat < mail.txt > mail2.txt [root@centos8 ~]# cat mail2.txt hello how old you [root@centos8 ~]# cat mail.txt hello how old you [root@centos8 ~]# mail -s 邮件主题 邮箱账号 < mail.txt
把多行发送给STDIN
- 使用“<<终止词”命令从键盘把多行重导向给STDIN
- 直到 终止词 位置的所有文本都发送给STDIN
- 有时被称为就地文本(heretext)
管道
管道
-
管道(使用符号\“|”表示)用来连接命令
-
command1 |command2 |command3…
-
将命令1的STDOUT发送给命令2的STDIN,命令2的STDOUT发送到命令3的STDIN
-
STDERR(标准错误)默认不能通过管道转发,可利用2>&1 或 |& 实现
-
最后一个命令会在当前shell进程的子shell进程中执行用来
-
组合多种工具的功能
范例:转换为大写字母
[root@centos8 ~]# ls | tr 'a-z' 'A-Z'
范例:less实现分页地查看输入
[root@centos8 ~]# ls -l /etc | less
范例:mail 通过电子邮件发送输入
[root@centos8 ~]# echo "test mail" | mail -s "test" 邮箱地址
范例:算数运算
echo "2^3" | bc
管道中的 - 符号
管道中有时候会使用-符号
范例:
将/homed里面的文件打包,但打包的数据不是记录到文件,而是传送到stdout,经过管道后,将tar -cvf - /home传送给后面的tar - xvf - ,后面的这个 - 则是取前一个命令的stdout ,因此,就不需要使用临时file了。
tar - cvf - /home | tar -xvf -
tee
-
重定向到多个目标
命令1 | tee [-a ] 文件名 | 命令2 "把command1的标准输出保存在文件中,然后管道输入给command2"
①命令1的STDOUT保存在文件中,做为命令2的输入
②-a 追加 -
使用:
♦ 保存不同阶段的输出
♦ 复杂管道的故障排除
♦ 同时查看和记录输出范例:
ls /boot | tee ls.log | tr ‘a-z’ ‘A-Z’
练习
-
将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中
cat /etc/issue | tr [a-z] [A-Z] >> /tmp/issue.out
-
将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中
who | tr [a-z] [A-Z] >> /tmp/who.out
-
一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:Hello, I am 用户名,The system version is here,please help me to check it ,thanks!操作系统版本信息
mail -s "help" root <<EFO > Hello ,I am `whoami`,The system version is here,please help me to check it ,thanks! > `cat /etc/centos-release` > EFO
-
将/root/下文件列表,显示成一行,并文件名之间用空格隔开
ls /root | tr "\n" " "
-
计算1+2+3+..+99+100的总和
echo {1..100} | tr " " "+" | bc seq -s "+" 1 100 | bc
-
删除Windows文本文件中的回车字符,‘\r字符
yum -y install unix2dos dos2unix file unix2dos file
-
处理字符串“xt.,l 1 jr#!$mn 2 c*/fe 3 uz 4”,只保留其中的数字和空格
echo 'xt.,l 1 jr#clearmn 2 c*/fe 3 uz 4' | tr -dc "[0-9 ]"
-
将PATH变量每个目录显示在独立的一行
echo $PATH | tr ":" "\n"
-
将指定文件中0-9分别替代成a-j
tr [0-9] [a-j] < file.txt
-
将文件/etc/centos-release中每个单词(由字母组成)显示在独立一行,并无空行
cat /etc/centos-release | tr -sc "[:alnum:]." "\n"
-
下面那一个选项结果不一样 ( B )
A app.sh > f1.log 2>&1
B app.sh 2>&1 > f1.log
C app.sh 2>f1.log 1>&2
D app.sh &>f1.log -
4、在/home/stud1/wang目录下有一文件file,使用(d)可实现在后台执行命令,此命令将file中的内容输出到file.copy文件中。
a. cat file > file.copy
b. cat > file.copy
c. cat file file.copy &
d. cat file > file.copy &
-
如何保存linux历史命令并显示命令操作是时间?
HISTTIMEFORMAT="%F %T "
永久生效写在/etc/profile或~/.bash_profile export HISTTIMEFORMAT="%F %T "