Linux中极为重要的特性:重定向

1. I/O 重定向

“I/O” 代表输入/输出,通 过这个工具,你可以将命令的输入来源以及输出地点重定向为文件。也可以把多个命令连接起 来组成一个强大的命令管道。接下来列举下将会用到得命令:

cat  -连接文件
• sort -排序文本行
• uniq -报道或省略重复行
• grep -打印匹配行
• wc   -打印文件中换行符,字,和字节个数
• head -输出文件第一部分
• tail -输出文件最后一部分
• tee  -从标准输入读取数据,并同时写到标准输出和文件

2.标准输入、输出和错误

我们需要先了解下标准输入、输出和错误

输出经常由两种类型组成。第一, 程序运行结果;这是说,程序要完成的功能。第二,我们得到状态和错误信息,这些告诉我们程序进展。如果我们观察一个命令,像 ls,会看到它的运行结果和错误信息显示在屏幕上。 与 Unix主题“任何东西都是一个文件”保持一致,程序,比方说 ls,实际上把他们的运行 结果输送到一个叫做标准输出的特殊文件(经常用 stdout 表示),而它们的状态信息则送到另 一个叫做标准错误的文件(stderr)。默认情况下,标准输出和标准错误都连接到屏幕,而不是保存到磁盘文件。

除此之外,许多程序从一个叫做标准输入(stdin)的设备得到输入,默认情 况下,标准输入连接到键盘

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

3.标准输出重定向

I/O 重定向允许我们来重定义标准输出的地点。我们使用 “>” 重定向符后接文件名将标准输出重定向到除屏幕以外的另一个文件。为什么我们要这样做呢?因为有时候把一个命令的运行结果存储到一个文件很有用处。例如,我们可以告诉 shell 把 ls 命令的运行结果输送到文件ls-output.txt 中去,由文件代替屏幕

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

我们检查一下重定向的命令输出结果:

$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 167878 2008-02-01 15:07 ls-output.txt

如果我们用 less 阅读器来查看这个文件,我们会看到文件ls-output.txt 的确包含 ls 命令的执行结果

$ less ls-output.txt

重复重定向测试把目录换成一个不存在的目录

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

一个错误信息。因为我们指定了一个不存在的目录/bin/usr, 但是为什么这条错误信息显示在屏幕上而不是被重定向到文件 ls-output.txt

答案是,ls 程序不把它的错误信息输送到标准输出。许多写得不错的 Unix 程序,ls 把错误信息送到标准错误。因为我们只是重定向了标准输出,而没有重定向标准错误,所以错误信息被送到屏幕。马上,我们将知道怎样重定向标准错误,但是看一下输出文件发生了什么

$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 0 2008-02-01 15:08 ls-output.txt

文件长度为零!这是因为,当我们使用 “>” 重定向符来重定向输出结果时,目标文件总是从开头被重写。因为我们 ls 命令没有产生运行结果,只有错误信息,重定向操作开始重写文件,然后由于错误而停止,导致文件内容清空。

事实上,如果我们需要清空一个文件内容(或者创建一个新的空文件),可以使用这样的技巧:

$ > ls-output.txt

简单地使用重定向符,没有命令在它之前,这会清空一个已存在文件的内容或是创建一个新的空文件

所以,怎样才能把重定向结果追加到文件内容后面,而不是从开头重写文件?为了这个目的,我们使用 “>>” 重定向符,像这样:

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

使用 “>>” 操作符,将导致输出结果添加到文件内容之后。如果文件不存在,文件会被创建,就如使用了 “>” 操作符。把它放到测试中:

$ ls -l /usr/bin >> ls-output.txt
$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 503634 2008-02-01 15:45 ls-output.txt

我们重复执行命令三次,导致输出文件大小是原来的三倍

4.标准错误重定向

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

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

文件描述符 “2”,紧挨着放在重定向操作符之前,来执行重定向标准错误到文件 ls-error.txt任务

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

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

$ ls -l /bin/usr > ls-output.txt 2>&1

使用这种方法,我们完成两个重定向。首先重定向标准输出到文件 ls-output.txt,然后重定 向文件描述符 2(标准错误)到文件描述符1(标准输出)使用表示法 2>&1。(&>或2>&1作用:同时将错误信息、普通信息一并重定向输出到指定文件。)
注意重定向的顺序安排非常重要。标准错误的重定向必须总是出现在标准输出重定向之后,要不然它不起作用。上面的例子

>ls-output.txt 2>&1

重定向标准错误到文件 ls-output.txt,但是如果命令顺序改为:

2>&1 >ls-output.txt

则标准错误定向到屏幕。
现在的 bash 版本提供了第二种方法,更精简合理的方法来执行这种联合的重定向。

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

在这个例子里面,我们使用单单一个表示法 &> 来重定向标准输出和错误到文件 ls-output.txt。

6.处理不需要的输出

有时候我们不想要一个命令的输出结果,尤其适用于错误和状态信息。系统通过重定向输出结果到一个叫做 “/dev/null” 的特殊文件,为我们提供了解决问题的方法。这个文件是系统设备,叫做位存储桶,它可以接受输入,并且对输入不做任何处理。为了隐瞒命令错误信息,我们这样做:

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

接下来介绍利用标准输入得命令:

7.cat -连接文件

cat 命令读取一个或多个文件,然后复制它们到标准输出,就像这样:

cat [file]

在大多数情况下,你可以认为 cat 命令相似于 DOS 中的 TYPE 命令。你可以使用 cat 来显示文件而没有分页,例如:

$ cat ls-output.txt

将会显示文件 ls-output.txt 的内容。cat 经常被用来显示简短的文本文件。因为 cat 可以接受不只一个文件作为参数,所以它也可以用来把文件连接在一起。比方说我们下载了一个大型文件,这个文件被分离成多个部分(USENET 中的多媒体文件经常以这种方式分离),我们想把它们连起来。
我们能用这个命令把它们连接起来:

cat movie.mpeg.0* > movie.mpeg

因为通配符总是以有序的方式展开,所以这些参数会以正确顺序安排。让我们试着做些其他的工作。如果我们输入不带参数的 “cat” 命令,会发生什么呢:

$ cat

如果 cat 没有给出任何参数,它会从标准输入读入数据,又因为标准输入默认情况下连接到键盘,所以它正在等待我们输入数据

$ cat
The quick brown fox jumped over the lazy dog.

下一步,输入 Ctrl-d(按住 Ctrl 键同时按下 “d”),来告诉 cat,在标准输入中,它已经到达文件末尾(EOF)
由于没有文件名参数,cat 复制标准输入到标准输出,所以我们看到文本行重复出现。我们可以使用这种行为来创建简短的文本文件。比方说,我们想创建一个叫做 “lazy_dog.txt” 的文件,这个文件包含例子中的文本。我们这样做:

$ cat > lazy_dog.txt
The quick brown fox jumped over the lazy dog.

输入命令,其后输入要放入文件中的文本。记住,最后输入 Ctrl-d。通过使用这个命令,实现了世界上最低能的文字处理器
看一下运行结果,使用 cat 来复制文件内容到标准输出:

$ cat lazy_dog.txt
The quick brown fox jumped over the lazy dog.

现在我们知道 cat 怎样接受标准输入,除了文件名参数,重定向标准输入:

$ cat < lazy_dog.txt
The quick brown fox jumped over the lazy dog.

使用“<”重定向操作符,把标准输入源从键盘改到文件lazy_dog.tx。我们看到结果和传递单个文件名作为参数的执行结果一样。把这和传递一个文件名参数作比较,不是特别有意义,但它是用来说明把一个文件作为标准输入源。

8.管道线

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

command1 | command2

为了全面地说明这个命令,我们需要一些命令。它是 less 命令。我们用 less 来一页一页地显示任何命令的输出,命令把它的运行结果输送到标准输出:

$ ls -l /usr/bin | less

使用这项技术,可以方便地检测会产生标准输出的任一命令的运行结果。

9.过滤器

管道线经常用来对数据完成复杂的操作。有可能会把几个命令放在一起组成一个管道线。通常,以这种方式使用的命令被称为过滤器。过滤器接受输入,以某种方式改变它,然后输出它。

第一个我们想试验的过滤器是 sort。想象一下,我们想把目录/bin 和/usr/bin 中的可执行程序都联合在一起,再把它们排序,然后浏览执行结果:

$ ls /bin /usr/bin | sort | less

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

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

uniq 命令经常和 sort 命令结合在一起使用。uniq 从标准输入或单个文件名参数接受数据有序列表(详情查看 uniq 手册页),默认情况下,从数据列表中删除任何重复行。

所以,为了确信我们的列表中不包含重复句子(这是说,出现在目录/bin 和/usr/bin 中重名的程序),我们添加 uniq 到我们的管道线中:

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

在这个例子中,我们使用 uniq 从 sort 命令的输出结果中,来删除任何重复行。如果我们想 看到重复的数据列表,让 uniq 命令带上> “-d” 选项(uniq -d:显示重复出现的行):

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

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

wc(字计数)命令是用来显示文件所包含的行数、字数和字节数。例如:

$ wc ls-output.txt
7902 64566 503634 ls-output.txt

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

查看我们的有序列表中程序个数,我们可以这样做:

$ ls /bin /usr/bin | sort | uniq | wc -l
2728

12.grep -打印匹配行

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

grep pattern [file...]

当 grep 遇到一个文件中的匹配 “模式”,它会打印出包含这个类型的行。grep 能够匹配的模式可以很复杂,但是现在我们把注意力集中在简单文本匹配上面。在后面的章节中,我们将会研究高级模式,叫做正则表达式。

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

$ ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
gunzip
...

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

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

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

$ head -n 5 ls-output.txt
total 343496
...
$ tail -n 5 ls-output.txt
...

它们也能用在管道线中:

$ ls /usr/bin | tail -n 5
znew
...

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

$ tail -f /var/log/messages
Feb 8 13:40:05 twin4 dhclient: DHCPACK from 192.168.1.1
....

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

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

为了和我们的管道隐喻保持一致,Linux 提供了一个叫做 tee 的命令,这个命令制造了一个 “tee”,安装到我们的管道上。tee程序从标准输入读入数据,并且同时复制数据到标准输出(允许数据继续随着管道线流动)和一个或多个文件。当在某个中间处理阶段来捕捉一个管道线的内容时,这很有帮助。

这里,我们重复执行一个先前的例子,这次包含 tee 命令,在 grep 过滤管道线的内容之前,来捕捉整个目录列表到文件ls.txt:

$ ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
....
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值