第六章-重定向<The Linux Command Line A Complete Introduction>

一.学习内容

1.在本课中,我们将展示命令行最酷的特性。它被称为I/O重定向。“I/O”代表输入/输出,使用这个工具,您可以重定向命令的输入和输出进出文件,以及将多个命令连接到强大的命令管道中。为了展示这个功能,我们将介绍以下命令:

cat连接文件

sort对文本行进行排序

uniq报告或省略重复行

grep打印匹配模式的行

wc打印每个文件的换行、字和字节计数

head输出文件的第一部分

tail输出文件的最后一部分

tee从标准输入读取并写入标准输出和文件


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

1.到目前为止,我们使用的许多程序都会产生某种输出。这种输出通常由两种类型组成。


•项目结果;也就是说,程序设计要产生的数据
•状态和错误信息,告诉我们程序是如何进行的


2.如果我们看一下像ls这样的命令,我们可以看到它在屏幕上显示其结果和错误消息。
与Unix“一切都是文件”的主题保持一致,像ls这样的程序实际上将它们的结果发送到一个称为标准输出(通常表示为stdout)的特殊文件,并将它们的状态消息发送到另一个文件

三.重定向标准输出


1.I/O重定向允许我们重新定义标准输出的位置。要将标准输出重定向到另一个文件而不是屏幕,我们使用>重定向操作符,后跟文件名。我们为什么要这么做?将命令的输出存储在文件中通常很有用。例如,我们可以告诉shell将ls命令的输出发送到文件ls-output.txt而不是屏幕


[me@linuxbox ~]$ ls -l /usr/bin > ls-output.txt

2.在这里,我们创建了/usr/bin目录的长清单,并将结果发送到文件ls-output.txt。让我们检查一下命令的重定向输出,如下所示:


[me@linuxbox ~]$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 167878 2018-02-01 15:07 ls-output.txt

3.很好,一个漂亮的大文本文件。如果我们查看带有less的文件,我们将看到文件ls-output.txt确实包含ls命令的结果。


[me@linuxbox ~]$ less ls-output.txt

4.现在,让我们重复我们的重定向测试,但这一次有所改变。我们将把目录名更改为不存在的目录名。


[me@linuxbox ~]$ ls -l /bin/usr > ls-output.txt
ls: cannot access /bin/usr: No such file or directory

5.我们收到一条错误信息。这是有意义的,因为我们指定了不存在的目录/bin/usr,但是为什么错误消息显示在屏幕上,而不是重定向到文件ls-output.txt?答案是ls程序不会将错误消息发送到标准输出。
相反,像大多数编写良好的Unix程序一样,它将错误消息发送给标准错误。因为我们只重定向了标准输出而不是标准错误,所以错误消息仍然被发送到屏幕上。稍后我们将看到如何重定向标准错误,但首先让我们看看输出文件发生了什么。


[me@linuxbox ~]$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 0 2018-02-01 15:08 ls-output.txt

6.该文件现在的长度为零!这是因为当我们使用>重定向操作符重定向输出时,目标文件总是从头重写。因为我们的ls命令没有生成任何结果,只有一条错误消息,所以重定向操作开始重写文件,然后因为错误而停止导致它被截断。事实上,如果我们需要截断一个文件(或者创建一个新的空文件),我们可以使用这样的技巧:


[me@linuxbox ~]$ > ls-output.txt

7.简单地使用重定向操作符,前面没有任何命令,将截断现有文件或创建一个新的空文件。
那么,我们如何将重定向输出附加到文件中,而不是从一开始就覆盖文件呢?为此,我们使用>>重定向操作符,如下所示:


[me@linuxbox ~]$ ls -l /usr/bin >> ls-output.txt

8.使用>>操作符将导致输出被追加到文件中。
如果文件不存在,就像使用了>操作符一样创建它。让我们来验证一下。


[me@linuxbox ~]$ ls -l /usr/bin >> ls-output.txt
[me@linuxbox ~]$ ls -l /usr/bin >> ls-output.txt
[me@linuxbox ~]$ ls -l /usr/bin >> ls-output.txt
[me@linuxbox ~]$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 503634 2018-02-01 15:45 ls-output.txt

9.我们重复该命令三次,得到的输出文件是原来的三倍大。


四.重定向标准错误

1.重定向标准错误缺乏专用重定向操作符的便利性。为了重定向标准错误,我们必须引用它的文件描述符。程序可以在几个编号的文件流中的任何一个上产生输出。虽然我们将前三个文件流称为标准输入、输出和错误,但shell在内部将它们引用为文件描述符0、1和
2,分别。shell提供了使用文件描述符号重定向文件的表示法。因为标准错误与文件描述符2相同,所以我们可以用t重定向标准错误


[me@linuxbox ~]$ ls -l /bin/usr 2> ls-error.txt

2.文件描述符2被放在重定向操作符之前,用于执行将标准错2》误重定向到文件ls-error.txt的操作。

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

4.在某些情况下,我们可能希望将命令的所有输出捕获到单个文件中。为此,我们必须同时重定向标准输出和标准错误。有两种方法可以做到。这里显示的是传统的方法,它适用于旧版本的shell:


[me@linuxbox ~]$ ls -l /bin/usr > ls-output.txt 2>&1

5.使用这种方法,我们执行了两次重定向。首先,我们将标准输出重定向到文件ls-output.txt,然后使用符号2>&1将文件描述符2(标准错误)重定向到文件描述符1(标准输出)。

6.注意重定向的顺序是重要的
标准错误的重定向必须始终在重定向标准输出之后发生,否则它将不起作用。下面的示例将标准错误重定向到文件ls-output.txt:


>ls-output.txt 2>&1

7.如果顺序更改为以下,则标准错误将直接显示在屏幕上:


2>&1 >ls-output.txt

8.最新版本的bash提供了第二种更精简的方法来执行这种组合重定向,如下所示:


[me@linuxbox ~]$ ls -l /bin/usr &> ls-output.txt

9.在本例中,我们使用&>符号将标准输出和标准错误重定向到文件ls-output.txt。你也可以像这样将标准输出和标准错误流附加到单个文件中:


[me@linuxbox ~]$ ls -l /bin/usr &>> ls-output.txt


五.处理不需要的输出

1.有时候“沉默是金”,我们不想要命令的输出;我们只是想把它扔掉。这尤其适用于错误和状态消息。通过将输出重定向到一个名为/dev/null的特殊文件,系统提供了一种方法来做到这一点这个文件是一个系统设备,通常称为位桶,它接受输入,不处理输入。为了抑制来自命令的错误消息,我们这样做:


[me@linuxbox ~]$ ls -l /bin/usr 2> /dev/null

2./dev/null在Unix中
位桶是一个古老的Unix概念,由于它的通用性,它出现在Unix文化的许多部分。当有人说他们将你的评论发送到/dev/null时,现在你知道这是什么意思了。有关更多示例,请参阅Wikipedia关于/dev/null的文章


六.重定向标准输入

1.到目前为止,我们还没有遇到任何使用标准输入的命令(实际上我们有,但稍后我们将揭示这一点),因此我们需要介绍一个。
2.cat:连接文件
cat命令读取一个或多个文件,并将它们复制到标准输出中,如下所示:

cat filename
3.在大多数情况下,您可以将cat看作类似于DOS中的TYPE命令。您可以使用它来显示文件而不分页。例如,下面的命令将显示ls-output.txt文件的内容:
[me@linuxbox ~]$ cat ls-output.txt
4.Cat通常用于显示短文本文件。因为cat可以接受多个文件作为参数,所以它也可以用于将文件连接在一起。
假设我们下载了一个被分割成多个部分的大文件(多媒体文件在Usenet上通常是这样分割的),我们希望将它们重新连接在一起。如果文件命名如下:
movie.mpeg.001 movie.mpeg.002 ... movie.mpeg.099
5.我们可以用下面的命令把它们连接起来:
cat movie.mpeg.0* > movie.mpeg
6.因为通配符总是按排序顺序展开,所以参数将按正确的顺序排列。
这些都很好,但是这和标准输入有什么关系呢?还没有,但我们试试别的吧。如果我们不带参数输入cat会发生什么?
[me@linuxbox ~]$ cat
7.什么也不会发生;它就像挂在那里一样。看起来可能是这样,但它确实在做它应该做的事情。
如果cat没有给定任何参数,它将从标准输入读取,并且由于标准输入在默认情况下是连接到键盘的,因此它正在等待我们键入一些东西!尝试添加以下文本并按enter键:
[me@linuxbox ~]$ cat
The quick brown fox jumped over the lazy dog.
8.接下来,输入ctrl-D(即按住ctrl键并按下D),告诉cat它已到达标准输入的文件结束(EOF)
[me@linuxbox ~]$ cat
The quick brown fox jumped over the lazy dog.
The quick brown fox jumped over the lazy dog.
9.在没有filename参数的情况下,cat将标准输入复制到标准输出,因此我们看到重复的文本行。我们可以使用这种行为来创建短文本文件。假设我们想创建一个名为lazy_dog.txt的文件,其中包含示例中的文本。我们会这样做:
[me@linuxbox ~]$ cat > lazy_dog.txt
The quick brown fox jumped over the lazy dog.
10.键入命令,后面跟着要放在文件中的文本。
记得在最后键入ctrl-D。使用命令行,我们实现了世界上最愚蠢的文字处理器!要查看结果,可以使用cat再次将文件复制到stdout。
[me@linuxbox ~]$ cat lazy_dog.txt
The quick brown fox jumped over the lazy dog.
11.现在我们知道了cat如何接受标准输入(除了文件名参数),让我们尝试重定向标准输入。
[me@linuxbox ~]$ cat < lazy_dog.txt
The quick brown fox jumped over the lazy dog.
12.使用< redirection操作符,我们将标准输入源从键盘更改为文件lazy_dog.txt。我们看到,结果与传递单个文件名参数相同。与传递filename参数相比,这并不是特别有用,但它用于演示使用文件作为标准输入源。其他命令更好地利用了标准输入,我们很快就会看到。
在我们继续之前,请查看cat的手册页,因为它有几个有趣的选项。

六.Pipelines

1. 命令从标准输入读取数据并将其发送到标准输出的能力被称为管道的shell特性所利用。使用管道操作符|,一个命令的标准输出可以通过管道连接到另一个命令的标准输入。

command1 | command2
2.为了充分演示这一点,我们将需要一些命令。
还记得我们说过有一个我们已经知道可以接受标准输入的吗?它是更少。我们可以使用less逐页显示将结果发送到标准输出的任何命令的输出。
[me@linuxbox ~]$ ls -l /usr/bin | less
3.这是非常方便的!使用这种技术,我们可以方便地检查产生标准输出的任何命令的输出。
4.过滤器
管道通常用于对数据执行复杂的操作。可以将几个命令放在一个管道中。通常,以这种方式使用的命令称为过滤器。过滤器接受输入,以某种方式改变它,然后输出。我们要尝试的第一个是sort。想象一下我们重定向55想要在/bin和/usr/bin,将它们按顺序排列,并查看结果列表。
[me@linuxbox ~]$ ls /bin /usr/bin | sort | less
5.因为我们指定了两个目录(/bin和/usr/bin),所以ls的输出将由两个排序列表组成,每个列表对应一个目录。通过在管道中包含sort,我们将数据更改为生成单个排序列表。
6.≥与|的区别
乍一看,可能很难理解管道操作符|与重定向操作符>执行的重定向。简单地说,重定向操作符将命令与文件连接起来,而管道操作符将一个命令的输出与另一个命令的输入连接起来。

Command1 > file1 Command1 | command2

很多人在学习管道时都会尝试以下操作,“只是为了看看会发生什么”:command1 > command2
回答:有时候真的很糟糕。
下面是一位管理基于linux的服务器设备的读者提交的实际示例。作为超级用户,他这样做了:
# CD /usr/bin
# ls > less
第一个命令将它放在大多数程序存储的目录中,第二个命令告诉shell使用ls命令的输出更少地覆盖文件。由于/usr/bin目录已经包含了一个名为less的文件(less程序),第二个命令用ls中的文本覆盖less程序文件,从而破坏了系统上的less程序。
这里的教训是,重定向操作符会静默地创建或覆盖文件,因此您需要非常尊重它。


七.uniq:报告或省略重复行

1.uniq命令通常与sort一起使用。Uniq接受来自标准输入或单个文件名参数(参见Uniq手册页了解详细信息)的排序数据列表,默认情况下,从列表中删除任何重复项。所以,为了确保我们的列表没有重复的。第6章是,任何出现在/bin和/usr/bin目录下的同名程序,我们将把uniq添加到我们的管道中。

[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | less
2.在本例中,我们使用uniq从排序命令的输出中删除任何重复项。如果我们想看到重复的列表,我们给uniq添加-d选项,如下所示:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq -d | less
3.wc:打印行、字和字节计数
wc (word count)命令用于显示文件中包含的行数、字数和字节数。这里有一个例子:
[me@linuxbox ~]$ wc ls-output.txt
7902 64566 503634 ls-output.txt
4.在本例中,它打印出三个数字:ls-output.txt中包含的行、字和字节。与前面的命令一样,如果在没有命令行参数的情况下执行,wc接受标准输入。-l选项将其输出限制为仅报告行。将它添加到管道中是一种方便的计数方法。要查看已排序列表中的项数,可以这样做:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | wc -l
2728
5. grep:打印与图案匹配的行
6.Grep是一个功能强大的程序,用于查找文件中的文本模式。它是这样使用的:
grep pattern filename
7.当grep在文件中遇到“模式”时,它打印出包含该模式的行。grep可以匹配的模式可能非常复杂,但现在我们将集中于简单的文本匹配。我们将在第19章介绍称为正则表达式的高级模式。
假设我们想要在程序列表中找到名称中嵌入了单词zip的所有文件。这样的搜索可能会让我们对系统中与文件压缩有关的一些程序有所了解。我们会这样做:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
gunzip
gzip
unzip
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

8.grep有几个方便的选项。
•-i,使grep在执行搜索时忽略大小写(通常搜索是区分大小写的)
•-v,告诉grep只打印那些不匹配模式head/tail的行:
9.print First/Last Part of Files
有时您不需要命令的所有输出。您可能只需要前几行或最后几行。head命令打印文件的前10行,tail命令打印最后10行。默认情况下,这两个命令打印10行文本,但可以使用-n选项进行调整。

[me@linuxbox ~]$ head -n 5 ls-output.txt
total 343496
-rwxr-xr-x 1 root root 31316 2017-12-05 08:58 [
-rwxr-xr-x 1 root root 8240 2017-12-09 13:39 411toppm
-rwxr-xr-x 1 root root 111276 2017-11-26 14:27 a2p
-rwxr-xr-x 1 root root 25368 2016-10-06 20:16 a52dec
[me@linuxbox ~]$ tail -n 5 ls-output.txt
-rwxr-xr-x 1 root root 5234 2017-06-27 10:56 znew
-rwxr-xr-x 1 root root 691 2015-09-10 04:21 zonetab2pot.py
-rw-r--r-- 1 root root 930 2017-11-01 12:23 zonetab2pot.pyc
-rw-r--r-- 1 root root 930 2017-11-01 12:23 zonetab2pot.pyo
lrwxrwxrwx 1 root root 6 2016-01-31 05:22 zsoelim -> soelim

10.这些也可以在管道中使用:


[me@linuxbox ~]$ ls /usr/bin | tail -n 5
znew
zonetab2pot.py
zonetab2pot.pyc
zonetab2pot.pyo
zsoelim

11.Tail有一个允许您实时查看文件的选项。这对于在日志文件被写入时监视其进度非常有用。在下面的示例中,我们将查看/var/log中的消息文件(如果消息丢失,则查看/var/log /syslog文件)。在某些Linux发行版上执行此操作需要超级用户权限,因为/var/log/messages文件可能包含安全信息。


[me@linuxbox ~]$ tail -f /var/log/messages
Feb 8 13:40:05 twin4 dhclient: DHCPACK from 192.168.1.1
Feb 8 13:40:05 twin4 dhclient: bound to 192.168.1.4 -- renewal in 1652 seconds.
Feb 8 13:55:32 twin4 mountd[3953]: /var/NFSv4/musicbox exported to both 192.168.1.0/24 and
twin7.localdomain in 192.168.1.0/24,twin7.localdomain
Feb 8 14:07:37 twin4 dhclient: DHCPREQUEST on eth0 to 192.168.1.1 port 67
Feb 8 14:07:37 twin4 dhclient: DHCPACK from 192.168.1.1
Feb 8 14:07:37 twin4 dhclient: bound to 192.168.1.4 -- renewal in 1771 seconds.
Feb 8 14:09:56 twin4 smartd[3468]: Device: /dev/hda, SMART Prefailure Attribute: 8 Seek_Time_
Performance changed from 237 to 236
Feb 8 14:10:37 twin4 mountd[3953]: /var/NFSv4/musicbox exported to both 192.168.1.0/24 and
twin7.localdomain in 192.168.1.0/24,twin7.localdomain
Feb 8 14:25:07 twin4 sshd(pam_unix)[29234]: session opened for user me by (uid=0)
Feb 8 14:25:36 twin4 su(pam_unix)[29279]: session opened for user root by me(uid=500)

12.使用-f选项,tail将继续监视文件,当添加新行时,它们将立即出现在显示中。这个过程一直持续到您键入ctrl-C。

八.tee - 从标准输入和输出读取到标准输出和文件

1.为了与管道比喻保持一致,Linux提供了一个名为tee的命令,用于在管道上创建一个“tee”配件。tee程序读取标准输入并将其复制到标准输出(允许数据沿着管道继续)和一个或多个文件中。这对于在处理的中间阶段捕获管道的内容非常有用。
这里我们重复前面的一个例子,这一次包括tee在grep过滤管道内容之前将整个目录列表捕获到文件ls.txt中:


[me@linuxbox ~]$ ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
gunzip
gzip
unzip
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

九.总结

与往常一样,请查看本章所介绍的每个命令的文档。我们只看到了它们最基本的用法。它们都有许多有趣的选择。随着我们获得Linux经验,我们将看到命令行的重定向特性非常有用解决专门的问题。有许多命令使用标准输入和输出,几乎所有命令行程序都使用标准错误来显示它们的信息消息。


Linux是关于想象力的

当我被要求解释Windows和Linux之间的区别时,我经常使用一个玩具类比。
Windows就像一个Game Boy。你去商店买了一个崭新的盒子。你把它带回家,打开它,玩它。漂亮的画面,可爱的声音。但过了一段时间,你就会厌倦它附带的游戏,所以你会回到商店购买另一款游戏。这样的循环不断重复。最后,你回到商店,对柜台后的工作人员说:“我想要一款具有这种功能的游戏!,却被告知不存在这样的游戏,因为它没有“市场需求”。然后你说:“但我只需要改变这一件事!”背后的人然后你说:“但我只需要改变这一件事!”柜台后面的人说你不能换。所有的游戏都被密封在他们的墨盒里。你发现你的玩具仅限于别人认为你需要的游戏。

另一方面,Linux就像世界上最大的安装工具。你打开它,里面是一大堆零件。有很多钢支柱、螺丝、螺母、齿轮、滑轮、马达,还有一些关于建造什么的建议。所以,你开始摆弄它。你提出一个又一个建议。过了一段时间,你会发现你对做什么有自己的想法。你再也不用去商店了,因为你已经有了你需要的一切。
安装组呈现出你想象的形状。它做你想要的。

当然,你对玩具的选择是个人的事情,那么你觉得哪种玩具更令人满意呢?

相关推荐

  1. Linux

    2023-12-07 06:04:04       36 阅读
  2. 三十 配置 Web Gateway 的默认参数 - ASP 定向

    2023-12-07 06:04:04       37 阅读
  3. Redies

    2023-12-07 06:04:04       38 阅读
  4. Redies

    2023-12-07 06:04:04       31 阅读
  5. Qt对话框

    2023-12-07 06:04:04       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-07 06:04:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-07 06:04:04       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-07 06:04:04       87 阅读
  4. Python语言-面向对象

    2023-12-07 06:04:04       96 阅读

热门阅读

  1. 绘制动态心形图的MATLAB代码

    2023-12-07 06:04:04       75 阅读
  2. 【WPF】扫描的方式发现局域网中的Android设备

    2023-12-07 06:04:04       54 阅读
  3. 【第二章】用于基因组数据分析的 R 简介

    2023-12-07 06:04:04       53 阅读
  4. C++ 引用

    2023-12-07 06:04:04       55 阅读
  5. WordPress发布文件随机设置作者昵称信息

    2023-12-07 06:04:04       56 阅读
  6. 图像处理领域的应用

    2023-12-07 06:04:04       59 阅读
  7. 第三章 核心设计与架构:

    2023-12-07 06:04:04       54 阅读
  8. stable-diffusion-webui

    2023-12-07 06:04:04       65 阅读
  9. Css实现小球边界碰撞回弹

    2023-12-07 06:04:04       57 阅读