本节书摘来自异步社区《UNIX编程环境》一书中的第1章,第1.2节,作者:【美】Brian W. Kernighan , Rob Pike著,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.2 文件和常用命令
在UNIX系统中信息存储在文件中,它很像日常的办公室文件。每个文件有名字、内容、存放地点以及某些管理信息,诸如所有者以及文件大小等。文件可能是一封信,或者是人名及地址清单,或者是源程序,或者是供某个程序用的数据,甚至是程序的可执行形式以及其他的非文本类型材料。
UNIX文件组织结构使你可以维护自己的文件而不会影响其他人的文件,并且也防止他人干涉你的文件。UNIX系统有大量的程序可操作文件,但是现在,我们只介绍最频繁使用的那些。第2章是关于文件系统的具体讨论,其中介绍了许多与文件有关的其他命令。
1.2.1 创建文件
如果想录入一篇文章、一封信或一个程序,那么怎样把这些信息存放在机器中呢?这类任务大多是用文本编辑器完成的,它是一个在计算机中保存和操作信息的程序。在每个UNIX系统中几乎都有一个屏幕编辑器,它利用现代终端的特点,显示你对文件所进行的编辑效果。两个最流行的文本编辑器是vi和emacs。在这里我们不介绍任何屏幕编辑器,其原因部分是由于篇幅所限,部分是由于不存在一个标准的文本编辑器。
不过,有一个名为ed的编辑器肯定在你的系统中存在。它不需要特定的终端功能,因此可以在任何终端上工作。它也构成了其他基本程序的基础(包括一些屏幕编辑器),所以这个程序是非常值得学习的。附录A中有关于这个程序的简要说明。
无论我们偏好哪个编辑器,都得熟练掌握以便能够创建文件。这里我们以ed为例进行讨论,这也可保证你能在自己的系统中完成这些例子,当然你可以使用自己最喜好的编辑器。
要用ed建立一个文件junk,可按如下操作进行:
命令a(append)通知ed开始接收文本。“.”指明文本结束,但必须出现在一行的开始处。不要忘掉这个命令,否则任何其他ed命令都不会被识别——所键入的一切都会被认为是所添加的文本。
编辑命令w(write)存储所键入的信息。w junk是把内容存放在名为junk的文件中。文件名可以任意起(之所以选择junk这个词,是因为该文件不重要)。
w命令之后,ed显示键入到文件中的字符数。在w命令之前,不会有永久性的存储,所以如果退出系统下班回家,有关的信息不会存储到文件中去(如果在编辑时退出系统,所有的数据会存放在名为ed.hup的文件中,这样下一次可以继续使用)。如果正在编辑时系统崩溃(比如由于软件或硬件的故障而突然停机),该文件只存放最后一次用写命令时所保存的内容。而在w之后,信息就永久地保存了。以后可以键入如下命令再访问该文件:
当然,你可以编辑所键入的文本,如纠正拼写错误,修改用词,重新排列段落等。当这些都完成之后,可用q(quit)命令退出编辑器。
1.2.2 列出文件
创建以下两个文件,junk和temp:
字符数从ed开始计数到每一行的结尾,结尾称为换行,系统用它来表示回车键。
ls命令列出文件的名称(并非内容):
这就是刚创建的那两个文件(当然也还会有其他人建立的其他文件)。文件名自动按字母顺序排列。
如同多数命令一样,ls有各种选项用以替代默认功能。在命令行中选项跟随着命令名,通常由“-”和一个代表其含义的字母构成。例如,ls-t使文件按“时间”顺序排列,最后一次修改的文件,最先列出
-l给出了一个“长”的列表,为每个文件提供了更多信息:
total2说明文件占据硬盘的数据块数量,一个数据块通常有512或1024个字符。字串-rw-r--r--说明读写权限。在本例中,所有者(你自己)可以读写,但其他人只能读。后面跟随的1是该文件的链接数量,将在第2章讨论。you是文件的所有者,即创建文件的人。19和22是对应文件的字符数,它们同从ed所得到的数字是一致的。而日期和时间则说明了文件是何时进行最后修改的。
选项可以组合在一起:ls–lt会得到同ls-l一样的数据,但是按照较新文件先列出的原则排序。-u选项说明文件何时被使用:ls–lut按照最新使用的次序,列出一个长(-l)的清单。-r选项反转输出的顺序,所以ls-rt按最早使用的次序排列。也可以只列出感兴趣的文件名字,命令如下:
在命令行中命令后面的字符串,诸如上面例子中的-l和junk,称为程序参数。参数通常是命令所使用的文件名字或选项。
通常的惯例是用负号和单个字母指定选项,诸如-t,或字母组合-lt。一般而言,如果命令接收这类选项,它们应置于文件名参数之前,但可以按任意的次序出现。UNIX程序在对多选项的处理上是不一致的。例如,标准第7版的ls不会接受
作为ls–lt的同义词,在别的程序中,多重选择项则要求被分开书写。
在学习更多例子之后,你会发现对于选项参数几乎不存在什么规划或系统性。每个命令都有其各自的语法规则,以及关于字母的各种含义(通常同一个功能在不同的命令中有不同的含义)。这种不可预见的行为使人不适应,而且常常被看作系统的缺陷而加以引证。尽管情况正在改善——新的版本通常有较好的一致性——我们仍旧建议,在编写程序时尽可能做得更好些,同时在手边保留一份手册。
1.2.3 显示文件
若现在有了一些文件,那么怎么查看其内容呢?有太多的程序可以完成这项工作。一种方式是使用编辑器:
ed先显示junk中的字符数目。命令1,$p通知印出文件中所有的行。在学会如何使用编辑器后,你可以选择要显示出的部分。
有时候使用编辑器显示并不太合适。举例来说,编辑器ed有处理文件大小的限制—仅限于数千行的文件。另外,它一次只能显示一个文件,而有时可能需要显示若干个文件,一个接一个,中间不间断,所以这里介绍几个其他办法。
首先是cat,在所有显示命令中,它是最简单的。cat显示其参数列出的所有文件的内容:
给定名字的文件在终端上被连接(catenate)1(从而有了名称cat)在一起,其一个接一个相连,没有间隙。
对短小的文件这么做没有问题,但是对于较长的文件,如果与计算机连接的速率较快,则必须用Ctrl + s迅速停止由cat导出的输出,否则它们就全部从屏幕上流逝了。尽管每个UNIX系统几乎都有这样的命令,但并不存在一个“标准”的命令,可以在可视终端上一次一屏地显示一份文件。你所用的系统中也许有一个称为pg或者more的命令。我们所使用的是p,在第6章中将介绍它。
类似于cat,pr命令也可显示出文件名清单中文件的全部内容,但它是以一种在行式打印机上适用的模式显示:每页66行(11英寸),附有最后一次修改文件的日期和时间、页码、页眉上的文件名,以及跨越两页的附加行。这样,可以只显示junk,然后跳到新的一页开始显示temp:
pr可以输出多列格式:
这表示以3列的形式显示每个文件。你可以使用其他合理的列数,pr会尽其可能完成。Pr-m可以按并行列的形式,显示若干文件。请参见pr(1)。
需要注意的是,pr并不是可以重新排列行及调整边距的排版程序。真正的排版程序是nroff以及troff,将在第9章讨论。
还有可以在高速打印机上打印文件的命令。请在手册中观看名称为lp及lpr的命令,或者在手册索引中查找“printer”(打印机)。至于使用哪一个命令,取决于连接到系统的设备是什么。pr和lpr经常一起用,用pr对信息做合适的格式处理,再用lpr将其传送至行式打印机上。稍后还会讨论这些内容。
1.2.4 移动、复制和删除文件
现在来看看其他命令。首先是修改文件的名字。改名是通过把文件从一个名字“变动”到另一个名字来完成的,比如:
其作用是把名为junk的文件改名为precious,而文件内容并没有改变。如果再运行ls,会看见不同的一个清单,junk没有了,而precious出现了。
注意,如果把一个文件移往另一个已存在的文件,目标文件会被替换掉。
要复制一个文件副本(也就是,要某文件的两个版本),可以使用cp命令:
对precious制作一个名为precious.save的副本。
最后,如果你已厌倦了文件的创建和移动操作,rm命令可以清除列出的所有文件:
如果要删去的某个文件并不存在,会出现警告。除此以外,rm像多数UNIX命令一样安静地工作,没有提示符,也没有对话,出错信息很简洁,有时甚至没有用。太简单的表达对于初学者而言有些困难,而经验丰富的用户却认为对话多的命令让人厌烦。
1.2.5 文件名
到目前为止,我们并没有说明一个合法文件名应符合哪些要求,现在是说明这些规则的时侯了。首先,文件名长度不应超过14个字符。其次,尽管可以选择几乎所有的字符,但通常应选择那些明显的字符,并避免使用可能引起歧义的字符。例如,我们已看见在ls命令中,ls-t意味着按时间顺序。所以,如果有一个名为-t的文件,那么把它按名称列出来就很困难。(怎样做?)除了把负号作为首字符之外,还有一些字符也有特别的含义。在熟练掌握它们之前,为避免混乱,应该只使用字母、数字、点号和下划线(点号和下划线通常用于把文件名分成若干部分,如前例中的precious.save)。最后,不要忘了区分大小写—junk、Junk和JUNK是三个不同的名称。
1.2.6 有用的命令
我们有了创建文件、列出其名称并显示其内容的基本命令,现在可以学习几个文件处理的命令了。为使讨论更集中,将使用一个名为poem的文件,其内容是Argustus De Morgan的诗歌。先用ed创建该文件:
下面第一个命令用于计算文件的行数、词数和字符数。类似于计数命令w,我们把这一命令称为wc(word-counting):
也就是说,poem有8行,46个字,263个字符。“字”的定义很简单:任何不含空格、Tab键和新行的字符串。
wc可以为多个文件计数(并显示全部结果),它也可以在需要时,略去计数功能。参见wc(1)。
第二个命令为grep,它搜寻文件中的符合给定匹配模式的行(该名称来源于ed命令g/regular-expression/p,这在附录A中解释)。假如打算在poem中寻找单词“fleas”:
grep在使用-v选项时,会寻找所有不匹配给定模式的行(它来源于编辑器命令v,可以认为它是匹配的逆向使用)。
grep可以用于在多个文件中查询。此时,对每一查询的结果行,会加上文件名做为前缀,这样就知道匹配来源于哪个文件。另外,grep还有计数、编号等功能。它还能处理比一个字复杂得多的模式匹配,我们将在第4章中讨论该问题。
第3个命令是sort,它把输入内容按字母次序一行行的排序。对于诗句,这样做不是很有意义,但我们也进行一下处理,从而可以看看结果:
排序是逐行的,但默认排列顺序是空白行、大写字母、小写字母,所以它并不是严格地按字母排序的。
sort有很多控制排序方式的选项—逆序、数字序、字典序、略去前导空格序、按行内的字段排序等—不过通常只需要掌握部分选项,以下是最常用的选项。
第4章会进一步讨论sort。
另一个文件检查命令是tail,它印出文件的最后10行。所以这一命令对于上面的8行诗来说太多了,但它对于较大型的文件是有用的。另外,tail有指定行数的选项,这样可以印出poem的最后一行:
tail也可以用来指定从某行开始显示文件:
从第3行开始显示文件(请注意,作为参数的负号通常有逆向含义)。
最后一对命令用于比较文件。假设有一个poem的变种文件new_poem:
这两个文件没有多大的区别,实际上,要仔细观看才能找出差别。这时就要使用比较命令了。cmp找出两个文件第一个有区别的地方:
该结果说明,两文件不同之处在第2行。的确如此,但它没有说明其差别是什么,而且除了第一个差别之外,它就不再作其他的比较了。
另一个文件比较命令是diff,它报告所有被修改、增加或减少的行:
该结果说明,第一个文件(poem)的第2行已被改成了第2个文件(new_poem)的第2行,而第4行也存在不同之处。
一般而言,cmp用于判断两个文件是否确实内容相同。它工作快,适用于任何类型的文件,而不仅仅是文本文件。diff用于已知道文件之间可能有所差别,进而想准确地知道哪些行有什么不同的情况,它只适用于文本文件。
1.2.7 文件系统命令小结
表1-1列出了是到目前为止已讨论的处理文件的命令。