Linux 下强大得不得了的 IO 重定向

2020-07-08 00:00:00 命令 文件 标准 输出 重定向

在 Linux 下,I/O 重定向可以称为是命令行酷的特性了。命令的输入可以来自于键盘或者文件,输出可以打印在终端模拟器,也可以打印到文件,这里就需要用到 I/O 的重定向特性,利用 I/O 的重定向功能还可以实现强大的命令管道。你准备好去一探究竟了吗?

什么是 I/O 呢?简单一点,I 是 input,输入;O 是 output,输出。

今天我们将学习以下命令,从学习这些命令的使用方法来体会 I/O 重定向的酷炫特性。

  • cat:查看文件内容
  • sort:对文本内容排序
  • uniq:用于报告或忽略文件中的重复行,一般与sort命令结合使用
  • grep:找出匹配的行
  • wc:打印文件中换行符,字,和字节个数
  • head:输出文件开头部分
  • tail:输出文件结尾部分
  • tee:从标准输入读取数据,并同时写到标准输出和文件

1. 标准输入,标准输出和标准错误

标准输入:程序执行一般需要从标准输入(stdin)读取数据,一般标准输入设备是连接到键盘的。 标准输出:程序执行的过程中会产生结果,结果要显示出来就需要将结果输出到标准输出设备(stdout),一般标准输出设备连接到显示器。 标准出错:程序运行的工程中可能会有一些错误提示,这就需要输出到标准出错设备(stderr),一般标准出错设备也是连接到显示器的。

I/O 重定向允许我们更改输出地点和输入来源。一般地,输出到屏幕,输入来自键盘, 但是通过 I/O 重定向,我们可以做出改变。

2. 标准输出重定向

标准输出一般是输出到屏幕的,但是我们使用 I/O 的重定向功能可以将标准输出重定向到其他地方,比如一个文件。重定向需要使用 ">" 重定向符号实现。下面是一个例子:

ls -l /usr/bin > ls-output.txt

我们把 ls -l /usr/bin 的结果作为输入,使用 > 将其重定向到 ls-output.txt 这个文件。好了,这下看看在当前目录是不是多了一个 ls-output.txt 文件呢?顺便使用 less 命令看看里面的内容是什么?

不知道大家有没有注意到,我们单独输入 ls 命令的时候会在终端回显输出结果,就相当于把输出打印在屏幕上,但是使用了 > 重定向之后,终端没有回显了,而是把输出内容写到一个文件去了。再来看一个例子:

ls -l /bin/usr > ls-output.txt

这次我们查看的目录 /bin/usr 并不存在,所以终端会回显一行提示信息,这是标准出错信息,那这时候 ls-output.txt 文件里面应该是什么内容呢?是 ls -l /usr/bin > ls-output.txt 的结果吗?

我们发现 ls-output.txt 文件中没有内容了,这是为什么?其实 > 有重写的特性,我们执行 ls -l /bin/usr > ls-output.txt 的时候重写了这个文件,而重写的时候写入的是空内容,所以导致这个文件里面的内容没有了。

噢哦,有点有趣吧,那我们是不是可以使用 > file 来创建一个空文件呢?快去试试吧!

我们现在知道 > 的重写特性了,那我们既要保存文件中的内容,又要通过重定向的方式向文件中追加内容,那改怎么办呢?别着急,和 > 孪生的兄弟 >> 就是专门干这个事情的,大家可以试试将上面两个例子中的 > 换成 >> 试试,看看效果如何?当然你想看得更清楚一点 >> 的特性,你可以将第二个例子还一下,因为第二个例子是不会向文件写入新的内容的,ls -l /bin/usr 的输出为空,我们可以换成一个输出不为空的,比如:

ls -l /usr/bin >> ls-output.txt ls -l /usr/share/ >> ls-output.txt

执行完条命令的时候看看 ls-output.txt 的内容和文件大小,再执行第二条命令,对比一下结果,理解 >>> 的特性。

3. 标准错误重定向

标准错误重定向没有专用的重定向操作符。为了重定向标准错误,我们必须参考其文件描述符。 一个程序可以在几个编号的文件流中的任一个上产生输出。虽然我们已经将这些文件流的前 三个称作标准输入、输出和错误,shell 内部分别将其称为文件描述符 0、1 和 2。shell 使用文件描述符提供 了一种表示法来重定向文件。因为标准错误和文件描述符 2 一样,我们用这种 表示法来重定向标准错误:

ls -l /bin/usr 2> ls-error.txt

注意: 文件描述符 2,要紧挨着放在重定向操作符之前,中间没有空格。还是看看终端有没有回显,ls-error.txt 的内容吧。

4. 重定向标准输出和错误到同一个文件

可能有这种情况,我们希望捕捉一个命令的所有输出到一个文件。为了完成这个,我们必须同时重定向标准输出和标准错误。有两种方法来完成任务。

  • 个,传统的方法, 在旧版本 shell 中也有效:ls -l /bin/usr > ls-output.txt 2>&1
    • 使用这种方法,我们完成两个重定向。首先重定向标准输出到文件 ls-output.txt,然后 重定向文件描述符 2(标准错误)到文件描述符 1(标准输出)使用表示法 2>&1。

  • 现在的 bash 版本提供了第二种方法,更精简合理的方法来执行这种联合的重定向:ls -l /bin/usr &> ls-output.txt

5. 处理不需要的输出

有时候不想要一个命令的输出结果,只想把它们扔掉。系统通过重定向输出结果到一个叫做 "/dev/null" 的特殊文件, 为我们提供了解决问题的方法。这个文件是系统设备,叫做位存储桶,它可以 接受输入,并且对输入不做任何处理。

ls -l /bin/usr 2> /dev/null

6. 标准输入重定向

什么?输入也可以重定向,我有点吃惊,那我们一起来一探究竟吧。

6.1. cat

cat 命令读取一个或多个文件,然后复制它们到标准输出。试试 cat < ls-output.txt 吧。看看效果,其实我们是使用 < 输入重定向,把输入从键盘等输入设备改成从一个文件的内容作为输入。如果还没有理解,你可以在终端只输入 cat 命令,这时候没有任何响应,其实 cat 是在等待输入,我们键盘上随便输入一些内容,然后按 ctrl + d 告诉 cat 输入已经达到末尾,看看效果吧。

6.2. 管道线 |

命令从标准输入读取数据并输送到标准输出的能力被一个称为管道线的 shell 特性所利用。 使用管道操作符”|”(竖杠),一个命令的标准输出可以通过管道送至另一个命令的标准输入:

command1 | command2

来看个例子感受一下管道带来的便利吧。

ls -l /usr/bin | less

在这个例子中,我们将 ls -l /usr/bin 的结果当成 less 命令的输入。

6.3. 过滤器

管道线经常用来对数据完成复杂的操作。有可能会把几个命令放在一起组成一个管道线。 通常,以这种方式使用的命令被称为过滤器。过滤器接受输入,以某种方式改变它,然后输出它。个我们想试验的过滤器是 sort。想象一下,我们想把目录 /bin 和 /usr/bin 中 的可执行程序都联合在一起,再把它们排序,然后浏览执行结果:

ls /bin /usr/bin | sort | less

因为我们指定了两个目录(/bin 和 /usr/bin),ls 命令的输出结果由有序列表组成, 各自针对一个目录。通过在管道线中包含 sort,我们改变输出数据,从而产生一个有序列表。

6.4. uniq - 报道或忽略重复行

uniq 命令经常和 sort 命令结合在一起使用。uniq 从标准输入或单个文件名参数接受数据有序列表(详情查看 uniq 手册页),默认情况下,从数据列表中删除任何重复行。所以,为了保证我们的列表中不包含重复句子(也就是出现在目录 /bin 和 /usr/bin 中重名的程序),我们添加 uniq 到我们的管道线中:

ls /bin /usr/bin | sort | uniq | less

在这个例子中,我们使用 uniq 从 sort 命令的输出结果中,来删除任何重复行。如果我们想看到重复的数据列表,让 uniq 命令带上 "-d" 选项,就像这样:

ls /bin /usr/bin | sort | uniq -d | less

6.5. wc - 打印行数、字数和字节数

直接看例子:wc ls-output.txt

在这个例子中,wc 打印出来三个数字:包含在文件 ls-output.txt 中的行数,单词数和字节数, 正如我们先前的命令,如果 wc 不带命令行参数,它接受标准输入。”-l”选项限制命令输出只能 报道行数。添加 wc 到管道线来统计数据,是个很便利的方法。查看我们的有序列表中程序个数, 我们可以这样做:ls /bin /usr/bin | sort | uniq | wc -l

6.6. grep - 打印匹配行

grep 是个很强大的程序,用来找到文件中的匹配文本。这样使用 grep 命令:grep pattern [file...]

比如说,我们想在我们的程序列表中,找到文件名中包含单词 "zip" 的所有文件。这样一个搜索, 可能让我们了解系统中的一些程序与文件压缩有关系。这样做:

ls /bin /usr/bin | sort | uniq | grep zip

grep 有一些方便的选项:"-i" 使得 grep 在执行搜索时忽略大小写(通常,搜索是大小写 敏感的),"-v" 选项会告诉 grep 只打印不匹配的行。

6.7. head / tail - 打印文件开头部分/结尾部分

有时候你不需要一个命令的所有输出。可能你只想要前几行或者后几行的输出内容。 head 命令打印文件的前十行,而 tail 命令打印文件的后十行。默认情况下,两个命令 都打印十行文本,但是可以通过 "-n" 选项来调整命令打印的行数。

也可以结合 | 使用哦。

tail 有一个选项允许你实时地浏览文件。当观察日志文件的进展时,这很有用,因为它们同时在被写入。在以下的例子里,我们要查看目录 /var/log 里面的信息文件。在一些 Linux 发行版中,要求有超级用户权限才能阅读这些文件。

使用 "-f" 选项,tail 命令继续监测这个文件,当新的内容添加到文件后,它们会立即出现在屏幕上。这会一直继续下去直到你输入 ctrl + c。

6.8. tee - 从 Stdin 读取数据,并同时输出到 Stdout 和文件

tee 程序从标准输入读入数据,并且同时复制数据 到标准输出(允许数据继续随着管道线流动)和一个或多个文件。当在某个中间处理 阶段来捕捉一个管道线的内容时,这很有帮助。来看个例子,我们在 grep 过滤管道线的内容之前,来捕捉整个目录列表到文件 ls.txt:

ls /usr/bin | tee ls.txt | grep zip

注意到没有,我们使用 tee 将中间结果保存到了 ls.txt 文件中。

好了,今天的内容就到这里了,学会了这些重定向的方法,我们在使用 Linux 系统的过程中又多了一些方便。不要死记硬背,能用的地方多用,既能解决麻烦,又学会使用新技能,何乐而不为呢?

欢迎关注微信公众号:Linux 漫游之旅,新文章会在这个公众号,免费提供 CSDN 下载服务。

相关文章