【Linux】重定向与管道

Linux 里的重定向真是泰裤辣!

1. 准备工作

1.1 说在前面

生活中处处充满重定向,例如,小明周末正准备偷偷去鱼塘和朋友钓鱼,结果老婆一通电话,怕老婆的小明不得不把目的地重定向到菜市场去了;再例如,动态网站会根据一些业务需求,通过请求将页面重定向到其他页面…

因此,重定向可理解为“重新定方向转到其他位置”。

在Linux中,我们将输入输出结果的目的地转到其他文件中,这就是Linux 的 I/O重定向。

学习目标

  • 学习并了解 Linux I/O 重定向是什么
  • 通过命令,实现简单的重定向

学习方式

  • 对这些重定向与文件操作相关的命令有一定的了解,不需要死记硬背,大脑里留个印象,用到的时候通过命令手册查询详细用法

参考教程

1.2 知识准备

在正式学习重定向与管道相关之前,我们需要先学习几个命令,这些命令与接下来的学习紧密相连:

1.2.1 cat 读取/合并 文件

读取一个或多个文件,格式如下:

cat [file]

例如:

# 准备文件
[sharry@localhost ~]$ ls > test.txt
[sharry@localhost ~]$ cat test.txt
Desktop
Documents
Downloads
hhh.txt
Music
Pictures
Public
Templates
test.txt
Videos

其中,这里使用了接下来即将介绍的重定向操作来进行文件准备。从输出结果来看,cat命令和 less 命令很像。

当我们使用这个命令不加参数的时候,就会有一个很有趣的现象:cat一直执行下去,并不断接收并输出我们键入的内容,直到我们使用Ctrl + c终止它,例如:

[sharry@localhost ~]$ cat
123
123
^C
[sharry@localhost ~]$

1.2.2 uniq 报告或忽略重复行

这里先举个例子,在下面的章节中再作一个稍微详细的介绍:

[sharry@localhost ~]$ ls /bin /usr/bin/ | sort | uniq | less

读者可以执行一下这个命令来观察结果

1.2.3 wc 打印行数字数字节数

这个命令可不是咱们常去的WC啊,但是这个命令的作用也很好理解,即小标题所说的打印行数、字数和字节数


[sharry@localhost ~]$ wc hhh.txt
  2  18 118 hhh.txt

1.2.4 grep 打印匹配行

grep pattern [file ...]

grep 的具体使用在下文的管道中 再结合例子具体介绍。

1.2.5 head 打印文件头

直接举例子,直接打印这个文件的头3行:


[sharry@localhost ~]$ head -n 3 test.txt
Desktop
Documents
Downloads

1.2.6 tail 打印文件尾

和 head 命令一样,很好理解


[sharry@localhost ~]$ tail -n 5 test.txt
Pictures
Public
Templates
test.txt
Videos

2. I/O重定向

在Linux中的重定向主要指,将 I/O 的源或者目标重定向到指定的源或目标。这里主要介绍 I/O 的重定向。

2.1 标准I/O

在学习重定向之前,我们首先要了解 什么是标准输入、标准输出以及标准错误。

与UNIX“一切都是文件”的思想一致,类似于ls的程序实际上把它们的运行结果发送到了一个称为标准输出(standard output,通常表示为stdout)的特殊文件中,它们的状态信息则发送到了另一个称为标准错误(standard error,stderr)的文件中,默认情况下,标准输出和标砖错误都将被链接到屏幕上,并且不会被保存在磁盘文件中。

标准输入(standard input,表示为 stdin),默认连接到键盘。

简单来说,标准输入、标准输出以及标准错误 指的就是 Linux 默认的输入输出形式,即从键盘输入,运行结果在显示屏显示。

当我们要将输入的形式变更,或者将输出的结果保存在别的文件或其他外设中时,就要用到重定向了。

2.2 标准重定向

在 Linux 命令中,使用重定向操作符 >后面接文件名,就可以将标准输出重定向到另一个文件中

1.2.1 标准输出重定向

直接举个例子,我们要将 /usr/binls运行结果保存在一个文件中,可以执行:

[sharry@localhost ~]$ ls -l /usr/bin > ls-output.txt
[sharry@localhost ~]$ ls
Desktop  Documents  Downloads  ls-output.txt  Music  Pictures  Public  Templates  Videos
[sharry@localhost ~]$ less ls-output.txt

[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 103988 May 29 23:18 ls-output.txt

>后接的 文件名不存在时,会在当前工作区直接创建该文件并接收重定向的结果。

当要重定向的源不存在时,例如,在一个不存在的路径执行ls并试图将其输出结果重定向时,如果我们没有事先指明标准错误重定向,那么结果会直接输出到标准错误中:

[sharry@localhost ~]$ ls -l /hahah/123 >  hahah.txt
ls: cannot access /hahah/123: No such file or directory
[sharry@localhost ~]$ ls
Desktop  Documents  Downloads  hahah.txt  ls-output.txt  Music  Pictures  Public  Templates  Videos
[sharry@localhost ~]$ ls -l hahah.txt
-rw-rw-r--. 1 sharry sharry 0 May 29 23:13 hahah.txt

我们再做个实验,将不存在的路径ls并试图将其输出结果重定向到已存在的ls-output.txt文件中:

[sharry@localhost ~]$ ls -l /hahah/123 >  ls-output.txt
ls: cannot access /hahah/123: No such file or directory
[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 0 May 29 23:17 ls-output.txt

通过上述例子我们发现,当我们将 标准输出重定向到某个文件时,若该文件不存在,则会创建该文件并记录重定向的结果,当输出的源不存在时,默认会将错误信息输出到标准错误;当该文件存在时,如果我们不加其他参数或选项,则会覆写该文件。

如果我们不想覆写这个重定向的目标文件呢?首先我们要了解为什么会覆写这个文件:是因为默认情况下,重定向时会将重定向的输出内容从文件的头部开始写入,当这个文件已经有内容时,就会把内容从头部开始覆写掉。利用这个特性我们可以获得一种清空文件或者创建一个空文件的方法:

[sharry@localhost ~]$ > newfile.txt
[sharry@localhost ~]$ ls -l newfile.txt
-rw-rw-r--. 1 sharry sharry 0 May 29 23:28 newfile.txt
[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 103988 May 29 23:18 ls-output.txt
[sharry@localhost ~]$ > ls-output.txt
[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 0 May 29 23:29 ls-output.txt

回到前面提到的,当我们不想覆写这个重定向的目标文件时,我们可以选择在文件的尾部开始输出内容,使用重定向符>>实现:

[sharry@localhost ~]$ ls -l /usr/bin/ >  ls-output.txt
[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 103988 May 29 23:33 ls-output.txt
[sharry@localhost ~]$ ls -l /hahha/123456 >> ls-output.txt
ls: cannot access /hahha/123456: No such file or directory
[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 103988 May 29 23:33 ls-output.txt
[sharry@localhost ~]

[sharry@localhost ~]$ less ls-output.txt >> ls-output.txt
[sharry@localhost ~]$ ls -l ls-output.txt
-rw-rw-r--. 1 sharry sharry 210484 May 29 23:37 ls-output.txt

2.2.2 标准错误重定向

在上面的小节中,我们发现,当我们重定向时没有添加其他参数的时候,报错信息会定向到标准错误,即默认显示在屏幕中。这个标准错误也可以重定向到文件中。

当我们想将标准错误重定向到某个文件中时,首先需要了解文件描述符 file descriptor。shell 将生成的内容发送到任意文件流时,文件流的前3个分别对应标准输入文件, 标准输出文件 和 标准错误文件 . 其索引值分别为 0 , 1, 2 。

因此, 当我们想要进行标准错误重定向时, 可以在重定向符前加上重定向文件流的索引值, 标准错误的索引值为 2 ,即 :

[sharry@localhost ~]$ ls -l /hahah/123456 2> hhh.txt
[sharry@localhost ~]$ less hhh.txt

至此,我们已经完成了标准输入与输出重定向的入门,并对文件描述符file descriptor 对文件流的索引作了一定了解。在实际使用的过程中,当我们想将标准输入和输出重定向到同一个文件中时,可以采用联合重定向,方法为 重定向符前的文件索引变为&,例如

[sharry@localhost ~]$ ls -l /hahah/123456 &>> hhh.txt
[sharry@localhost ~]$ ls -l hhh.txt
-rw-rw-r--. 1 sharry sharry 118 May 30 04:23 hhh.txt

本小节的末尾,再介绍一种重定向到 /dev/null特殊文件的方法。/dev/null文件是一个位桶(bit bucket)的系统设备,它接受输入但是不做任何处理。重定向到这个文件 表示对这个 重定向信息作一个忽略处理,例如:


[sharry@localhost ~]$ ls -l /hahah/123456 &>> /dev/null

2.2.3 标准输入重定向

在开头,我们就快速学习了一下 cat命令的基本使用,需要注意的是,这里的cat并不指猫!

好了,言归正传,我们先解释一下为什么当cat不加任何参数执行时,会不断接收并输出我们键入的数据:如果cat没有给定任何参数,它将从标准输入读取内容,默认情况下标准输入连接到的是键盘,因此我们不断地键入输入,它就不断地读取并输出当前行。

我们再试一次, 这次我们用Ctrl + D ,告知命令已达到标准输入的文件尾,而不是用Ctrl + c 中断进程。

[sharry@localhost ~]$ cat
Hello world
Hello world

使用cat命令创建短文件
利用cat命令不加任何参数执行时的特性,我们可以将输入的内容直接重定向到文件中,即从键盘输入就创建了文件。
例如:

[sharry@localhost ~]$ cat > helloworld.txt
Hello world! Linux is beautiful !
[sharry@localhost ~]$ cat helloworld.txt
Hello world! Linux is beautiful !

标准输入重定向
使用重定向符号<我们可以将标准输入的源从键盘变为目标文件,例如,我们将上面例子的helloworld文件作为输入源:

[sharry@localhost ~]$ cat < helloworld.txt
Hello world! Linux is beautiful !

3. 管道

命令从标准输入到读取数据,并将数据发送到标准输出其实是使用了 shell 的管道特性。使用管道操作符|可以将一个命令的标准输出传送到另一个命令的标准输入中,例如:

[sharry@localhost ~]$ ls -l /usr/bin/ | less

我们通常使用组合命令在使用管道的强大功能,这里我们用开头提到过的命令来进行一波体验

3.1 过滤器

管道功能经常用来对数据执行复杂的操作。也可以把多命令合在一起构成一个 管道。这种方式中用到的命令通常被称为过滤器( filter)。 过滤器接受 输入, 按照某种方式对输入进行改变,然后再输出它。
例如,我们想要将 /bin, /usr/bin目录下的所有可执行程序合并成一个列表,并且按照顺序排序,最后再查看这个列表:


[sharry@localhost ~]$ ls /bin /usr/bin/ | sort | less

3.2 组合命令

有了过滤器的概念,以及管道的基本介绍,接下来,我们就可以使用开头我们学习过的命令组合起来,体验管道的强大功能

3.2.1 uniq 重复行处理

结合sort以及管道,uniq可以报告或忽略文件中重复的行,相当于在输出结果时做了一次去重。

uniq可以 接收来自于标准输入或者单个文件名参数对应的已排序数据列表,默认情况下,该命令删除列表中所有重复的行。在管道中添加uniq,可以确保所有的列表没有重复行,例如:


[sharry@localhost ~]$ ls /bin /usr/bin/ | sort | uniq | less

当想 查看 重复行列表时, 添加 -d 选项


[sharry@localhost ~]$ ls /bin /usr/bin/ | sort | uniq -d | less

3.2.2 wc 打印行数信息

wc命令其实 和 cat命令 一样,当没有带参数时,会默认连接到标准输入,即键盘:


[sharry@localhost ~]$ wc
wc
wc
      2       2       6

结合管道, 我们可以用这个命令实现计数功能,如:


[sharry@localhost ~]$ ls /bin /usr/bin | sort | uniq | wc -l
1745

其中,-l 选项表示只打印行数

3.3.3 grep 打印匹配行

grepgrep 既可以 匹配 模式, 也可以 匹配 简单的文本。这里我们就以简单的文本举例: 例如,我们想打印系统中与 zip 相关的程序:


[sharry@localhost ~]$ ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
bzip2recover
funzip
gpg-zip
gunzip
gzip
mzip
unzip
unzipsfx
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

[sharry@localhost ~]$ ls /bin /usr/bin | sort | uniq | grep zip | wc -l
16

3.3.4 head 与 tail

结合管道,输出目标的头或尾。
有了上面的基础,这里就比较简单了,我们直接举例看效果:


bunzip2
bzip2
bzip2recover
[sharry@localhost ~]$ ls /bin /usr/bin | sort | uniq | grep zip | tail -n 5
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

3.3.5 tee 从标准输入读取并输出到标准输出

当在某个中间处理阶段来捕获一个管道中的内容时,tee可以读取标准输入,再把读取到的内容复制到标准输出和一个或多个文件中去。

这个命令在开头没有提到,因为它通常需要结合管道来使用,例如,我们要在当前目录grep获取全部 txt 文件前,先将ls的信息保存在另一个txt文件中:


[sharry@localhost ~]$ ls -l | tee temp.txt | grep txt
-rw-rw-r--. 1 sharry sharry  34 May 30 05:39 helloworld.txt
-rw-rw-r--. 1 sharry sharry 118 May 30 04:23 hhh.txt
-rw-rw-r--. 1 sharry sharry   0 May 30 06:29 temp.txt
-rw-rw-r--. 1 sharry sharry  84 May 30 04:53 test.txt
[sharry@localhost ~]$ ls
Desktop  Documents  Downloads  helloworld.txt  hhh.txt  Music  Pictures  Public  Templates  temp.txt  test.txt  Videos
[sharry@localhost ~]$ less temp.txt
[sharry@localhost ~]$ cat temp.txt
total 12
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Desktop
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Documents
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Downloads
-rw-rw-r--. 1 sharry sharry  34 May 30 05:39 helloworld.txt
-rw-rw-r--. 1 sharry sharry 118 May 30 04:23 hhh.txt
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Music
drwxr-xr-x. 2 sharry sharry   6 May 30 04:48 Pictures
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Public
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Templates
-rw-rw-r--. 1 sharry sharry   0 May 30 06:29 temp.txt
-rw-rw-r--. 1 sharry sharry  84 May 30 04:53 test.txt
drwxr-xr-x. 2 sharry sharry   6 Apr 17 18:33 Videos

4. 总结

本文介绍了 Linux 中标准输入、标准输出及标准错误的基本概念,并介绍了管道的基本概念。通过本文列举的例子,我们发现通过管道,我们可以将很多命令组合起来使用,以达到特定的目的,解决仅使用单个命令功能的局限性。在实际的使用中,管道的强大远不仅仅是本文提到的Demo,结合其他命令,管道还有很多妙用以及有趣的地方,请读者有空多加探索!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值