在本课中,我们将释放命令行最酷的功能。这被称为I/O重定向(I/O redirection)。“I/O”代表输入/输出(input/outpu),通过此功能,我们可以将命令的输入和输出重定向到文件或从文件重定向,以及将多个命令连接在一起,形成强大的命令管道(pipelines)。为了展示此功能,我们将介绍以下命令:
cat
—— 连接文件sort
—— 对文本行进行排序uniq
—— 报告或省略重复的行grep
—— 打印与图案匹配的行wc
—— 打印每个文件的换行符、单词和字节数head
—— 输出文件的第一部分tail
—— 输出文件的最后部分tee
—— 从标准输入读取并写入标准输出和文件第六章:重定向标准输入输出和错误重定向标准输出组命令重定向标准错误将标准输出和标准错误重定向到一个文件处理不需要的输出Unix文化中的 /dev/null重定向标准输入cat
—— 连接文件管道>
和 |
的区别过滤器uniq
—— 报告或省略重复行wc
—— 打印行、单词,和字节计数grep
—— 打印与范式匹配的行head
/ tail
—— 打印文件的头部/尾部tee
—— 从Stdin读取并输出到Stout和文件总结Linux是关于想象力的
到目前为止,我们使用的许多程序都会产生某种输出。此输出通常由两种类型组成:
如果我们查看 ls
这样的命令,我们可以看到它在屏幕上显示其结果和错误消息。
遵循Unix的主题【一切都是文件】, ls
等程序实际上会将结果发送到一个名为标准输出(standard output ,通常表示为 stdout )的特殊文件,并将状态消息发送到另一个称为标准错误(standard error ,stderr )的文件。默认情况下,标准输出和标准错误都链接到屏幕,不保存到磁盘文件中。
此外,许多程序从称为标准输入(standard input ,stdin )的工具中获取输入,默认情况下,该工具连接到键盘。
I/O重定向允许我们更改输出的去向和输入的来源。通常,输出会显示在屏幕上,输入来自键盘,但通过I/O重定向,我们可以改变这一点。
I/O重定向允许我们重新定义标准输出的去向。为了将标准输出重定向到另一个文件而不是屏幕,我们使用>重定向运算符,后跟文件名。我们为什么要这样做?将命令的输出存储在文件中通常很有用。例如,我们可以告诉shell将 ls
命令的输出发送到文件 ls-output.txt ,而不是屏幕:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /usr/bin > ls-output.txt
在这里,我们创建了一个 /usr/bin 目录的长列表,并将结果发送到文件 ls-output.txt 。让我们检查一下命令的重定向输出,如下所示:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 167878 2025-02-01 15:07 ls-output.txt
很好——一个漂亮的大文本文件。如果我们用 less
命令查看文件,我们会看到文件 ls-output.txt 确实包含 ls
命令的结果:
xxxxxxxxxx
[me@linuxbox ~]$ less ls-output.txt
现在,让我们重复我们的重定向测试,但这次有一个转折。我们将把目录的名称更改为不存在的名称:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /bin/usr > ls-output.txt
ls: cannot access /bin/usr: No such file or directory
我们收到一条错误消息。这是有道理的,因为我们指定了不存在的目录 /bin/usr ,但为什么错误消息显示在屏幕上,而不是重定向到文件 ls-output.txt ?答案是 ls
程序不会将错误消息发送到标准输出。相反,与大多数编写良好的Unix程序一样,它将错误消息发送到标准错误(standard error - stderr)。由于我们只重定向了标准输出而不是标准错误,因此错误消息仍被发送到屏幕上。我们将在一分钟后看到如何重定向标准错误,但首先让我们看看输出文件发生了什么:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l ls-output.txt
-rw-rw-r-- 1 me me 0 2025-02-01 15:08 ls-output.txt
文件现在长度为零!这是因为当我们使用 >
重定向运算符重定向输出时,目标文件总是从头重写。由于我们的 ls
命令没有生成任何结果,只生成了一条错误消息,重定向操作开始重写文件,然后由于错误而停止,导致文件被截断。事实上,如果我们真的需要截断一个文件(或创建一个新的空文件),我们可以使用这样的技巧:
xxxxxxxxxx
[me@linuxbox ~]$ > ls-output.txt
只需使用重定向运算符,前面没有命令,就会截断现有文件或创建一个新的空文件。
那么,我们如何将重定向的输出追加(append)到文件中,而不是从头覆盖文件呢?为此,我们使用 >>
重定向运算符,如下所示:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /usr/bin >> ls-output.txt
使用 >>
运算符将导致输出被附加到文件中。如果文件不存在,则创建它就像使用了 >
运算符一样。让我们通过重复一个命令并将其输出附加到一个文件来进行测试:
xxxxxxxxxx
[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 2025-02-01 15:45 ls-output.txt
我们重复 ls
命令三次,得到一个三倍大的输出文件。
让我们想象一种情况,我们想执行一系列命令并将结果发送到日志文件。既然我们已经知道了,我们可以这样做:
xxxxxxxxxx
[me@linuxbox ~]$ command1 > logfile.txt
[me@linuxbox ~]$ command2 >> logfile.txt
[me@linuxbox ~]$ command3 >> logfile.txt
此序列中的第一个命令创建/截断一个名为 logfile.txt 的文件,随后的每个命令都将其输出附加到该文件中。这种技术会奏效,但打了很多多余的字。一定有更好的办法。
正如我们在上一章中看到的,我们可以将多个命令放在一行上,如下所示:
xxxxxxxxxx
[me@linuxbox ~]$ command1; command2; command3
因此,我们可以将所有命令和重定向放在一行上:
xxxxxxxxxx
[me@linuxbox ~]$ command1 > logfile.txt; command2 >> logfile.txt; command3 >> logfile.txt
但是,如果我们可以将序列视为具有单个输出流的单个实体呢?我们可以通过创建组命令(group command)来实现这一点。为此,我们用大括号字符包围我们的序列:
xxxxxxxxxx
[me@linuxbox ~]$ { command1; command2; command3; } > logfile.txt
当我们的序列被大括号包围时,shell会将其视为重定向的单个命令。请注意,shell要求大括号周围有空格,序列中的最后一个命令必须以分号或换行符终止。
重定向标准错误缺乏专用重定向运算符的易用性。要重定向标准错误,我们必须引用其文件描述符(file descriptor)。程序可以在几个编号的文件流中的任何一个上产生输出。虽然我们将前三个文件流称为标准输入、输出和错误,但shell在内部分别将它们称为文件描述符0、1和2。shell提供了一种使用文件描述符编号重定向文件的符号。由于标准错误与文件描述符编号2相同,我们可以用以下符号重定向标准错误:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /bin/usr 2> ls-error.txt
文件描述符“2”位于重定向运算符之前,用于将标准错误重定向到文件 ls-error.txt 。
在某些情况下,我们可能希望将命令的所有输出捕获到一个文件中。为此,我们必须同时重定向标准输出和标准错误。有两种方法可以做到这一点。这里显示的是传统方式,适用于旧版本的shell:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /bin/usr > ls-output.txt 2>&1
使用这种方法,我们执行两次重定向。首先,我们将标准输出重定向到文件 ls-output.txt ,然后使用符号 2>&1
将文件描述符2(标准错误)重定向到文件描述符1(标准输出)。
请注意,重定向的顺序很重要。标准错误的重定向必须始终在重定向标准输出后发生,否则将不起作用。以下示例将标准错误重定向到文件 ls-output.txt :
xxxxxxxxxx
>ls-output.txt 2>&1
但是,如果顺序更改为以下顺序,则标准错误将显示在屏幕上:
xxxxxxxxxx
2>&1 >ls-output.txt
最近版本的bash提供了第二种更简化的方法来执行这种组合重定向,如下所示:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /bin/usr &> ls-output.txt
在这个例子中,我们使用单一符号 &>
将标准输出和标准错误重定向到文件 ls-output.txt 。我们还可以将标准输出和标准错误流附加到一个文件中,如下所示:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /bin/usr &>> ls-output.txt
有时“沉默是金”(silence is golden),我们不希望命令输出,我们只想把它扔掉。这尤其适用于错误和状态消息。系统提供了一种方法,将输出重定向到一个名为 /dev/null 的特殊文件。这个文件是一个系统设备,通常被称为比特桶(bit bucket),它接受输入,什么也不做。为了抑制命令中的错误消息,我们这样做:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /bin/usr 2> /dev/null
比特桶是一个古老的Unix概念,由于其普遍性,它出现在Unix文化的许多地方。当有人说他/她正在将你的评论发送到 /dev/null 时,现在你知道这意味着什么了。有关更多示例,请参阅 维基百科上关于 /dev/null 的文章 。
x/dev/null
/dev/null(或称空设备)在类Unix系统中是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。
在程序员行话,尤其是Unix行话中,/dev/null被称为比特桶或者黑洞。
使用
空设备通常被用于丢弃不需要的输出流,或作为用于输入流的空文件。这些操作通常由重定向完成。
/dev/null是一个特殊文件,而不是目录,因此不能使用Unix命令mv将文件移动到其中。使用rm命令才是Unix中删除文件的正确方法。
本概念大致相当于CP/M,DOS和Microsoft Windows中的NUL:或单纯的NUL设备,Windows NT及其后续系统中的\Device\Null或NUL,Amiga中的NIL:,以及OpenVMS中的NL:。在基于.NET的Windows PowerShell中,相同的概念为$null。
计算机文化中的引用
在Unix程序员使用的科技行话中和隐喻经常使用这一概念,例如“请将投诉发送到/dev/null”,“我的邮件被存档到了/dev/null”,以及“重定向到/dev/null”,分别表示:“不要拿投诉来烦我”,“我的邮件被删掉了”,和“一边去”。iPhone Dev Team通常使用“可以向/dev/null捐款”,意为他们不接受捐款。
空设备也是科技幽默的常用主题之一,例如警告用户系统的/dev/null已经使用了98%。1995年愚人节一家德国杂志c't写道,一种增强的/dev/null芯片可以借由将数据转换成内部LED的闪光以有效的处理输入数据。
苹果公司也曾在2003年利用这个概念做过一则广告,“将其它牌子的UNIX都送进/dev/null”,表明运行Mac OS X的PowerBook包含了全部UNIX特性。
到目前为止,我们还没有遇到任何使用标准输入的命令(实际上我们有,但稍后我们会透露这个惊喜),所以我们需要介绍一个。
cat
—— 连接文件cat命令读取一个或多个文件并将其复制到标准输出,如下所示:
cat [file ...]
在大多数情况下,我们可以将 cat
视为类似于DOS中的 TYPE
命令。
我们可以使用它来显示文件,而无需分页。例如,以下内容将显示文件 ls-output.txt 的内容:
xxxxxxxxxx
[me@linuxbox ~]$ cat ls-output.txt
cat
常用于显示短文本文件。由于 cat
可以接受多个文件作为参数,因此它也可以用于将文件连接在一起。假设我们下载了一个被拆分为多个部分的大文件(多媒体文件在Usenet上通常以这种方式拆分),我们想将它们重新连接在一起。如果文件命名为:
movie.mpeg.001 movie.mpeg.002 ... movie.mpeg.099
我们可以使用以下命令将它们重新连接在一起:
xxxxxxxxxx
cat movie.mpeg.0* > movie.mpeg
由于通配符总是按排序顺序展开,因此参数将按正确的顺序排列。
这一切都很好,但这与标准输入有什么关系呢?还没有,但让我们试试别的。如果我们毫无异议地进入 cat
,会发生什么?
xxxxxxxxxx
[me@linuxbox ~]$ cat
什么也没发生,它只是像挂着一样坐在那里。这可能看起来是这样,但它确实在做它应该做的事情。
如果没有给 cat
任何参数,它就会从标准输入中读取,由于默认情况下标准输入是附加在键盘上的,它正在等待我们键入一些东西!尝试添加以下文本并按Enter键:
xxxxxxxxxx
[me@linuxbox ~]$ cat
The quick brown fox jumps over the lazy dog.
接下来,键入Ctrl - d (即按住Ctrl键并按“d”),告诉 cat
已经到达标准输入的文件末尾(end of file ,EOF):
xxxxxxxxxx
[me@linuxbox ~]$ cat
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
在没有文件名参数的情况下, cat
会将标准输入复制到标准输出,因此我们看到我们的文本行重复。我们可以使用此行为创建短文本文件。假设我们想创建一个名为 lazy_dog.txt 的文件,其中包含我们示例中的文本。我们将这样做:
xxxxxxxxxx
[me@linuxbox ~]$ cat > lazy_dog.txt
The quick brown fox jumps over the lazy dog.
键入命令,然后键入要放入文件中的文本。记得在末尾键入 Ctrl - d 。使用命令行,我们实现了世界上最愚蠢的(dumbest)文字处理器!为了查看我们的结果,我们可以使用 cat
再次将文件复制到stdout。
xxxxxxxxxx
[me@linuxbox ~]$ cat lazy_dog.txt
The quick brown fox jumps over the lazy dog.
现在我们知道了 cat
如何接受标准输入,除了文件名参数外,让我们尝试重定向标准输入。
xxxxxxxxxx
[me@linuxbox ~]$ cat < lazy_dog.txt
The quick brown fox jumps over the lazy dog.
使用 <
重定向运算符,我们将标准输入的来源从键盘更改为 lazy_dog.txt 文件。我们看到结果与传递单个文件名参数相同。与传递文件名参数相比,这并不是特别有用,但它可以用来演示如何将文件用作标准输入源。其他命令更好地利用了标准输入,我们很快就会看到。
在我们继续之前,请查看 cat
的手册页,因为它有几个有趣的选项。
命令从标准输入读取数据并发送到标准输出的能力被称为管道(pipelines)的shell功能所利用。使用管道运算符 |
(竖线),一个命令的标准输出可以通过管道传输到(be piped)另一个命令。
command1 | command2
为了充分证明这一点,我们需要一些命令。还记得我们说过有一个我们已经知道的接受标准输入的吗?这就是 less
。我们可以使用 less
逐页显示任何将结果发送到标准输出的命令的输出:
xxxxxxxxxx
[me@linuxbox ~]$ ls -l /usr/bin | less
这非常方便!使用这种技术,我们可以方便地检查任何产生标准输出的命令的输出。
>
和 |
的区别乍一看,可能很难理解管道运算符 |
与重定向运算符 >
执行的重定向。简单地说:
重定向运算符将命令与文件连接起来;
管道运算符将一个命令的输出与第二个命令的输入连接起来。
command1 > file1
command1 | command2
很多人在学习管道时会尝试以下方法,“只是为了看看会发生什么”:
command1 > command2
答案是:有时候真的很糟糕。
这是一个由管理基于Linux的服务器设备的读者提交的实际示例。作为超级用户,他这样做了:
xxxxxxxxxx
# cd /usr/bin
# ls > less
第一个命令将他放在存储大多数程序的目录中,第二个命令告诉shell用 ls
命令的输出覆盖文件 less 。由于 /usr/bin 目录中已经包含了一个名为 less 的文件(less
程序),第二个命令用 ls
中的文本覆盖了 less 程序文件,从而破坏了系统上的 less
程序。
这里的教训是, >
重定向运算符会自动创建或覆盖文件,因此您需要非常尊重它。
管道通常用于对数据执行复杂的操作。可以将多个命令放在一个管道中。通常,这种方式使用的命令被称为过滤器(filters)。过滤器接收输入,以某种方式(somehow)更改它,然后输出它。我们将尝试的第一个是 sort
(排序)。想象一下,我们想制作一个 /bin 和 /usr/bin 中所有可执行程序的组合列表,将它们按排序顺序排列,并查看结果列表:
xxxxxxxxxx
[me@linuxbox ~]$ ls /bin /usr/bin | sort | less
由于我们指定了两个目录(/bin 和 /usr/bin), ls
的输出将由两个排序列表组成,每个目录一个。通过在管道中包含 sort
,我们更改了数据以生成一个单独的排序列表。
sort
是一个功能强大的命令,具有许多功能和选项。我们将在第20章中详细介绍它们。
uniq
—— 报告或省略重复行uniq
命令通常与 sort
结合使用。 uniq
接受来自标准输入或单个文件名参数的排序数据列表(有关详细信息,请参阅 uniq
手册页),默认情况下,会从列表中删除任何重复项。因此,为了确保我们的列表没有重复项(即出现在 /bin 和 /usr/bin 目录中的任何同名程序),我们将在管道中添加 uniq
:
xxxxxxxxxx
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | less
在这个例子中,我们使用 uniq
从 sort
命令的输出中删除任何重复项。如果我们想看到重复项列表,我们可以在 uniq
中添加 -d
选项,如下所示:
xxxxxxxxxx
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq -d | less
wc
—— 打印行、单词,和字节计数wc
( word count,单词计数)命令用于显示文件中包含的行数、单词数和字节数。这里有一个例子:
xxxxxxxxxx
[me@linuxbox ~]$ wc ls-output.txt
7902 64566 503634 ls-output.txt
在这种情况下,它会打印出三个数字:行(lines)数、单词(words)数和 ls-output.txt 中包含的字节数。与我们之前的命令一样,如果在没有命令行参数的情况下执行, wc
接受标准输入。 -l
选项将其输出限制为仅报告行。将其添加到管道中是一种方便的计数方法。要查看排序列表中的项目数量,我们可以这样做:
xxxxxxxxxx
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | wc -l
2728
grep
—— 打印与范式匹配的行grep是一个功能强大的程序,用于在文件中查找文本范式(text patterns)。它是这样使用的:
grep pattern [file ...]
当 grep
在文件中遇到【范式】时,它会打印出包含它的行。 grep
可以匹配的范式可能非常复杂,但现在我们将专注于简单的文本匹配。我们将在第19章介绍高级模式,称为正则表达式(regular expressions)。
假设我们想找到程序列表中名称中嵌入单词 zip
的所有文件。这样的搜索可能会让我们了解系统中与文件压缩有关的一些程序。我们将这样做:
xxxxxxxxxx
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
gunzip
gzip
unzip
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit
以下是grep的一些方便的选项:
-i
,导致 grep
在执行搜索时忽略大小写(通常搜索区分大小写)-l
,使 grep
只输出包含与范式匹配的文本的文件名。-v
,使 grep
仅打印与模式不匹配的行。-w
,导致 grep
只匹配整个单词。head
/ tail
—— 打印文件的头部/尾部有时我们不希望命令的所有输出。我们可能只想要前几行或最后几行。 head
命令打印文件的前十行, tail
命令打印最后十行。虽然这两个命令默认打印十行文本,但可以使用 -n
选项指定行数。
xxxxxxxxxx
[me@linuxbox ~]$ head -n 5 ls-output.txt
total 343496
-rwxr-xr-x 1 root root 31316 2007-12-05 08:58 [
-rwxr-xr-x 1 root root 8240 2007-12-09 13:39 411toppm
-rwxr-xr-x 1 root root 111276 2007-11-26 14:27 a2p
-rwxr-xr-x 1 root root 25368 2006-10-06 20:16 a52dec
[me@linuxbox ~]$ tail -n 5 ls-output.txt
-rwxr-xr-x 1 root root 5234 2007-06-27 10:56 znew
-rwxr-xr-x 1 root root 691 2005-09-10 04:21 zonetab2pot.py
-rw-r--r-- 1 root root 930 2007-11-01 12:23 zonetab2pot.pyc
-rw-r--r-- 1 root root 930 2007-11-01 12:23 zonetab2pot.pyol
rwxrwxrwx 1 root root 6 2016-01-31 05:22 zsoelim -> soelim
这些命令也可以在管道中使用:
xxxxxxxxxx
[me@linuxbox ~]$ ls /usr/bin | tail -n 5
znew
zonetab2pot.py
zonetab2pot.pyc
zonetab2pot.pyo
zsoelim
将 -n
选项与 head
和 tail
一起使用,可以从文件中间剪切摘录。让我们假设我们有一个文本文件,它有一个5行的页眉和一个5行尾,我们想删除它,只留下中间包含数据的“好”部分。我们可以这样做:
xxxxxxxxxx
[me@linuxbox ~]$ head -n -5 text_header_footer.txt | tail -n +5 > text.txt
当与 head
一起使用时, -n
选项允许输出负值,这会导致除最后 n 行之外的所有行都被输出。类似地, tail
的 -n
选项允许一个加号,导致除前 n 行之外的所有行都被输出。
tail
还有一个选项,允许我们实时跟踪文件的内容。这对于在写入日志文件时查看日志文件的进度非常有用。在下面的示例中,我们将查看 /var/log 中的消息文件(如果缺少 messages
,则查看 /var/log/syslog 文件)。在某些Linux发行版上执行此操作可能需要超级用户权限,因为日志文件可能包含安全信息:
xxxxxxxxxx
[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)
使用 -f
选项, tail
会连续监视文件,当添加新行时,它们会立即出现在显示器上。这会一直持续到我们按 Ctrl-c 。
tee
—— 从Stdin读取并输出到Stout和文件为了与我们的管道比喻保持一致,Linux提供了一个名为 tee
的命令,可以在我们的管道上创建一个“tee”配件。 tee
程序读取标准输入并将其复制到标准输出(允许数据继续沿管道传输)和一个或多个文件。这对于在处理的中间阶段捕获管道的内容非常有用。在这里,我们重复前面的一个示例,这次包括 tee
,在 grep
过滤管道内容之前,将整个目录列表捕获到文件 ls.txt 中:
xxxxxxxxxx
[me@linuxbox ~]$ ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
gunzip
gzip
unzip
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit
与往常一样,请查看本章中介绍的每个命令的文档。我们只看到了它们最基本的用法。他们都有一些有趣的选择。随着我们获得Linux经验,我们将看到命令行的重定向功能对于解决特殊问题非常有用。有许多命令使用标准输入和输出,几乎所有的命令行程序都使用标准错误来显示其信息性消息。
当我被要求解释Windows和Linux之间的区别时,我经常用一个玩具类比。
Windows就像一个Game Boy。你去商店买一个盒子里闪闪发光的新东西。你把它带回家,打开它,玩它。漂亮的图形,可爱的声音。不过,过了一段时间,你会厌倦随附的游戏,所以你会回到商店再买一个。这个循环一次又一次地重复。最后,你回到商店,对柜台后面的人说:“我想要一款这样的游戏!”却被告知不存在这样的游戏,因为没有“市场需求”。然后你说,“但我只需要改变一件事!”柜台后面的人说你不能改变它。游戏都密封在墨盒里。你发现你的玩具仅限于其他人决定你需要的游戏。
另一方面,Linux就像世界上最大的安装程序集。你打开它,它只是一个巨大的零件集合。有很多钢支柱、螺钉、螺母、齿轮、滑轮、电机,以及一些关于建造什么的建议。所以,你开始玩它。你构建一个建议,然后是另一个。过了一段时间,你发现你对做什么有自己的想法。你永远不必回到商店,因为你已经有了你需要的一切。竖立器套装呈现出你想象中的形状。它做你想做的事。
当然,你对玩具的选择是个人的事情,那么你会觉得哪种玩具更令人满意呢?