重定向详解

标准输入、输出和错误

许多程序都会产生某种输出。此输出通常由两种类型。一种是程序的输出结果;也就是说,数据程序所产生的。另一种是某些状态或错误消息告诉我们程序进展如何。

如果我们查看像ls这样的命令,我们可以看到它在屏幕上显示其结果和错误消息。遵循“一切皆文件”,诸如ls之类的程序实际上将其结果保存到一个称为标准输出的特殊文件中(通常表示stdout),状态消息发送到另一个文件,称为标准错误stderr)。

默认情况下,标准输出和标准错误都输出到屏幕上,而不保存到磁盘文件中。另外,许多程序从称为标准输入(stdin)的设备(文件)中获取输入,默认情况下已连接到键盘

重定向标准输出

I/O重定向使我们可以重新定义标准输出的位置。重定向标准输出到另一个文件而不是屏幕,我们使用“>”or“>>”操作符重定向到文件。

[root@iZerb5rob3dcf6Z ~]# ls /usr/bin/ > stdout.txt
[root@iZerb5rob3dcf6Z ~]# less stdout.txt 
 ....
[root@iZerb5rob3dcf6Z ~]# ls /bin/usr > stdout.txt 
ls: 无法访问/bin/usr: 没有那个文件或目录
[root@iZerb5rob3dcf6Z ~]# ll stdout.txt 
-rw-r--r-- 1 root root 0 6月  11 19:07 stdout.txt

由于我们只重定向了标准输出而不是标准错误,该错误消息仍被发送到屏幕。而此时stdio.txt文件夹为空,这是因为,当我们使用“>”重定向输出时,始终从头开始重写目标文件。而ls命令没有产生任何结果,只有一条错误消息,重定向操作开始重写文件,然后由于错误而停止,导致其被截断。如果我们不想文件内容被覆盖则可以使用“>>”,此操作为追加:

[root@iZerb5rob3dcf6Z ~]# ll stdout.txt 
-rw-r--r-- 1 root root 97414 6月  11 19:15 stdout.txt
[root@iZerb5rob3dcf6Z ~]# ll /usr/bin/ >> stdout.txt 
[root@iZerb5rob3dcf6Z ~]# ll stdout.txt 
-rw-r--r-- 1 root root 194828 6月  11 19:15 stdout.txt

可以看大文件内容有所增长。

输出重定向:‘>’: 覆盖输出
          ‘>>’:追加输出

重定向标准错误

fd:file descriptor ,文件描述符

标准输入:0
标准输出:1
标准错误:2

Shell提供了使用文件描述符重定向的方法。由于标准错误与文件描述符编号2相匹配,所以我们可以使用以下符号重定向标准错误:

[root@iZerb5rob3dcf6Z ~]# ls -l /bin/usr 2> stderr.txt
[root@iZerb5rob3dcf6Z ~]# cat stderr.txt 
ls: 无法访问/bin/usr: 没有那个文件或目录
[root@iZerb5rob3dcf6Z ~]# 

将标准输出和标准错误输入到同一个文件

有两种方法可供选择:

  1. 将标准输出重定向到文件output.txt,然后将文件描述符2(标准错误)重定向到标准输出1(标准输出),使用符号2>&1
[root@iZerb5rob3dcf6Z ~]# ls -l /bin/usr > output.txt 2>&1
[root@iZerb5rob3dcf6Z ~]# cat output.txt 
ls: 无法访问/bin/usr: 没有那个文件或目录

请注意,重定向的顺序很重要

  1. 使用单符号&>重定向标准输出标准错误到文件output.txt。也可以追加标准输出和标准错误流到单个文件,如下所示:
[root@iZerb5rob3dcf6Z ~]# ls -l /bin/usr &> output.txt
[root@iZerb5rob3dcf6Z ~]# cat output.txt 
ls: 无法访问/bin/usr: 没有那个文件或目录
[root@iZerb5rob3dcf6Z ~]# ls -l /bin/usr &>> output.txt
[root@iZerb5rob3dcf6Z ~]# cat output.txt 
ls: 无法访问/bin/usr: 没有那个文件或目录
ls: 无法访问/bin/usr: 没有那个文件或目录
[root@iZerb5rob3dcf6Z ~]# 

处理不需要的输出

有时我们不想要程序的输出,只想要其执行返回状态。系统提供了一种通过将输出重定向到名为“/dev/null”的特殊文件来实现此目的的方法。该文件是一个称为比特桶的系统设备,它接受输入并且不执行任何操作。我们这样做:

[root@iZerb5rob3dcf6Z ~]# ls -l /bin/usr &> /dev/null 

重定向标准输入

以下我们将简单介绍使用标准输入的命令。

cat–串联文件

cat命令读取一个或多个文件,并将它们复制到标准输出,如下所示:

cat file ...

显示文件内容。cat常用来显示短片:

[root@iZerb5rob3dcf6Z ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
......

由于cat可以接受多个文件作为参数,因此它也可以用于将文件连接在一起。假设我们下载了一个大文件,该文件已拆分为多个文件部分,我们希望将它们重新组合。使用方法:

[root@iZerb5rob3dcf6Z ~]# echo 1 > movie1
[root@iZerb5rob3dcf6Z ~]# echo 2 > movie2
[root@iZerb5rob3dcf6Z ~]# echo 3 > movie3
[root@iZerb5rob3dcf6Z ~]# echo 4 > movie4
[root@iZerb5rob3dcf6Z ~]# cat movie{1,2,3,4}
1
2
3
4

如果输入不带参数的“cat”,它将从标准输入读取,因为标准输入默认情况下已连接到键盘,它正在等待我们输入内容!输入Ctrl-C告诉cat在标准输入上到达文件末尾(EOF):

[root@iZerb5rob3dcf6Z ~]# cat 
welcom to kingstar !
welcom to kingstar !
^C
[root@iZerb5rob3dcf6Z ~]# 
#我们可以使用此行为来创建短文本文件并且输出内容
[root@iZerb5rob3dcf6Z ~]# cat > cat.txt
welcom to kingstar !my name is Mr.YANG .
^C
[root@iZerb5rob3dcf6Z ~]# cat < cat.txt 
welcom to kingstar !my name is Mr.YANG .
[root@iZerb5rob3dcf6Z ~]# 

| 管道(pipe)

连接程序,实现将前一个命令的标准输出做为后一个命令的标准输入

[root@iZerb5rob3dcf6Z ~]# ls -l /usr/bin/ | less
总用量 148516
-rwxr-xr-x.   1 root root      41488 8月  20 2019 [
-rwsr-xr-x    1 root root      53048 10月 31 2018 at
lrwxrwxrwx    1 root root          2 4月  26 15:55 atq -> at
lrwxrwxrwx    1 root root          2 4月  26 15:55 atrm -> at
......
:q

| 与 > 的区别

重定向操将命令与文件连接起来,而管道操作将一个命令的输出传递给第二个命令的输入。

command1 > file1
command1 | command2

有的人可能会这样尝试:

[root@iZerb5rob3dcf6Z ~]# cat > cat 
safegra
^C
[root@iZerb5rob3dcf6Z ~]# cat cat 
safegra

而以下某些操作则可能会带来灾难:

[root@iZerb5rob3dcf6Z ~]# cd /usr/bin
[root@iZerb5rob3dcf6Z bin]# ls | less

这将会导致less命令被覆盖。重定向操作会静默创建或覆盖文件,因此您需要非常谨慎。

uniq - 报告或省略重复的行

uniq命令通常与sort结合使用。uniq接受排序列表作为标准输入或单个文件名参数的数据,并且默认情况下会从列表中删除所有重复项。

[root@iZerb5rob3dcf6Z ~]# cat num.txt | sort | uniq 
1
123
2
3
42
44
#如果要查看重复项列表
[root@iZerb5rob3dcf6Z ~]# cat num.txt | sort | uniq -c
      2 1
      1 123
      2 2
      2 3
      1 42
      1 44

wc – 打印行数,字数和字节数

wc(word count)命令用于显示行数,字数和字节数包含在文件中。例如:

[root@iZerb5rob3dcf6Z ~]# wc /etc/passwd
 21  30 920 /etc/passwd

在这种情况下,它将打印出三个数字:文件中包含的行,字和字节。就像我们之前的命令一样,如果不使用命令行参数执行,wc接受标准输入。“-l”选项显示行数。添加它连接到管道是一种方便的方法。我们可以这样做:

[root@iZerb5rob3dcf6Z ~]# cat num.txt | sort | uniq | wc -l
 6

grep –打印匹配模式的行

grep是一个功能强大的程序,用于在文件中查找文本模式。它的用法如下:

grep pattern [file...]

当grep在文件中遇到“模式”时,它会打印出包含该模式的行。

[root@iZerb5rob3dcf6Z ~]# ls /bin /usr/bin | sort | uniq | grep zip 
gpg-zip
gunzip
gzip
zip
zipcloak
zipnote
zipsplit

grep有几个方便的选项:“-i”使grep忽略大小写执行搜索时(通常搜索区分大小写),“-v”表示grep仅打印与模式不匹配的行。

head / tail

[root@iZerb5rob3dcf6Z ~]# head -n 5 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@iZerb5rob3dcf6Z ~]# tail -n 5 /etc/passwd
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
#也可以在管道里使用
[root@iZerb5rob3dcf6Z ~]# ls /usr/bin/ | tail -n 3
zmore
znew
zsoelim

tail有一个选项,可让您实时查看文件。这对于观看记录日志文件时的进度。

[root@iZerb5rob3dcf6Z ~]# tail -f -n 6 /var/log/messages
Jun 11 21:01:01 iZerb5rob3dcf6Z systemd: Started Session 359 of user root.
Jun 11 21:10:01 iZerb5rob3dcf6Z systemd: Started Session 360 of user root.
Jun 11 21:20:01 iZerb5rob3dcf6Z systemd: Started Session 361 of user root.
Jun 11 21:29:16 iZerb5rob3dcf6Z auditd[611]: Audit daemon rotating log files
Jun 11 21:30:01 iZerb5rob3dcf6Z systemd: Started Session 362 of user root.
Jun 11 21:40:01 iZerb5rob3dcf6Z systemd: Started Session 363 of user root.
Jun 11 21:45:48 iZerb5rob3dcf6Z systemd-logind: Removed session 333.
Jun 11 21:46:01 iZerb5rob3dcf6Z systemd: Started Session 364 of user root.
Jun 11 21:46:01 iZerb5rob3dcf6Z systemd-logind: New session 364 of user root.

tee

tee程序读取标准输入并将其复制到标准输出(允许数据继续沿管道传输)和一个或多个输出文件。

[root@iZerb5rob3dcf6Z ~]# ls /root/My_Hexo/ | tee root_My 
_config.yml
db.json
node_modules
package.json
package-lock.json
scaffolds
source
themes
yarn.lock
[root@iZerb5rob3dcf6Z ~]# cat root_My 
_config.yml
db.json
node_modules
package.json
package-lock.json
scaffolds
source
themes
yarn.lock

总结


版权声明:本文为m0_44947469原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。