RedHat Linux用户基础
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第2章 文件系统基础

2.1 文件系统导航

主要概念

➢ Linux文件系统是“倒置树”形的目录和文件,其根目录为“/”。

➢ 所有进程都有当前工作目录(current working directory),一般称作“cwd”。

➢ pwd命令显示bash Shell的当前工作目录。

➢ cd命令改变bash Shell的当前工作目录。

➢ 对文件的引用可以采用绝对引用或相对引用表示。

2.1.1 讲义

1.倒置树文件系统

以目录结构编排文件系统是很多计算机操作系统通用的方法。每个文件都有文件名(filename),再将文件名编排成目录(directory)(在有些操作系统里称为文件夹(folder))。目录本身也是一种文件,所以也可以将它们编排在另外的目录里。以此类推,层层组织,可以建立起一个结构性极强的环境。

例如,用户alice可能将几首歌曲保存为song1.midi和song2.midi的文件。这些歌曲可以收集在一个名为songs的目录中。用户alice可能还有一些名为picture1.png和picture2.png的图片文件。她可以将这些文件放在名为photos的目录中。songs和photos这两个目录可以编排在一个名为media的目录里。这个目录可能只是目录website中的几个目录之一。

这就像一棵树的分枝,如图2-1所示。website目录包含多个子目录。

图2-1 目录树图例

目录树(directory tree)的名字就是由图2-1中分枝的形状得来的。示例图一般画成分枝在下,树根(在这里是名为website的目录)在上,所以叫做倒置树(inverted tree)目录结构。

Linux使用一个目录树编排所有的文件和目录。所有的文件和目录都在根目录(root directory)的目录下面,这个目录名为“/”(读作“斜线”)。图2-2显示了目录树的一部分。

图2-2 目录树从“/”开始

图中的省略号表示这里有许多文件和目录没有显示出来。你可以看到该视图可进一步延伸,例如可以将如图2-1所示的目录树扩展到图2-2中的website目录,从而对整个目录树做进一步展开。在这里我们关心的是由“/”延伸出的结构,而不是其具体内容。

命名文件或目录的时候,从Linux文件系统树的根部开始,列出指向你想要的文件或目录的所有分枝目录,目录间用斜线(/)分开。这叫做项的全名(fully qualified name),简称FQN。举例来说,上述目录website的FQN为/home/alice/website。用户alice的文件song1.midi应被标为/home/alice/website/songs/song1.midi。文件名前面的一串目录名是这个文件的路径(path)。这种命名文件的方法保证每个文件和目录都有一个唯一的全名。在实际工作中,可以用相对引用简化文件名的输入。

2.使用Nautilus浏览目录树

在红帽企业版Linux X图形环境中,Nautilus是一个先进的工具,它可帮助用户导航文件系统。在红帽企业版Linux的桌面上,可以用鼠标左键双击左上角主目录(带小房子的)图标打开Nautilus窗口,如图2-3所示。

图2-3 Nautilus窗口

你也可以从应用程序菜单选择“系统工具”→“文件浏览器”,打开Nautilus浏览器(熟悉早期红帽企业版Linux的用户可能比较熟悉),如图2-4所示。

图2-4 Nautilus浏览器

图2-5 选择Nautilus树侧栏

Nautilus窗口的左侧栏为侧栏。侧栏有几个功能。我们现在只希望漫游目录树,右键单击侧栏顶部“位置”按钮,从弹出的菜单中选择“树”选项。

Nautilus窗口的左侧栏会以树形显示目录(文件夹)列表,最上面的目录为用户“主目录”,下面是“文件系统”。鼠标左键单击文件系统图标旁边的三角形图标展开目录。单击文件夹图标或文件夹名称,在Nautilus窗口的主栏展示文件夹内容。

图2-6 使用Nautilus漫游目录树

注意

当你选择查看某个目录的时候,主工具栏下方默认会以图标方式显示此目录的绝对引用(FQN),从“/”开始每一级目录用一个含目录名的按钮表示。花一些时间使用Nautilus浏览器漫游文件系统,查看目录内容。在左侧栏选择目录/etc/sysconfig/network-scripts,然后左键双击窗口主栏中的ifcfg-lo图标,即可查看文件/etc/sysconfig/network-scripts/ifcfg-lo的内容。

你已经花了一些时间学习目录树的概念及目录和文件绝对引用的组成,现在我们来看Linux文件系统的相关概念。

3.当前工作目录(cwd)

每个Linux进程(如程序、命令)运行时都会有一个默认指定的目录。如果一个文件没有指定开启它的FQN,那么它的默认目录就是它的FQN。这么做有两个作用:首先,进程可以简单地引用文件,不需要使用复杂的名称;第二,因为进程的动作在一定程度上取决于默认目录,这样做可使进程的运行更灵活。改变默认目录,进程的动作也会随之改变。这个默认目录就是进程的当前工作目录,即cwd。

一种认识目录的方式是将它作为一个地点而不是一个东西。如果这样理解的话,一个进程的cwd就是它现在的位置。如果进程的cwd改变,就是说将它从一个目录移动到另一个目录。这种认识目录的方式在Linux里是非常普遍的,所以表示地点的词汇会被经常用到。比如说,用户在讨论导航文件系统时,也就是在说他们从一个目录转移到另一个目录。

每个进程首先由启动它的父进程指定cwd。进程运行期间并不一定会被锁定在一个特定的cwd。有必要的话,进程可以在继续工作前将其cwd转移至另一个目录。

4.我在哪儿?pwd命令

在Linux系统运行的进程中,有一个叫做命令Shell(command Shell)的进程。如果你从系统的虚拟终端登录系统,或在X中启动一个终端程序,将会看到一个命令提示,要求你输入命令让系统执行。这个命令提示由负责读取和解释命令的Shell产生。红帽企业版Linux的默认命令Shell是bash(Bourne-again Shell)Shell。

与其他进程一样,bash Shell命令运行时会跟踪它的cwd。这一当前工作目录会影响到你在命令提示中输入的命令,成为这些命令运作时的cwd。也就是说,bash Shell命令的cwd就是你的cwd,也可以理解为你目前在系统中所处的位置。显然,跟踪这个cwd是非常重要的。这里有一些帮你确定cwd的方法。首先,命令提示会显示cwd路径的最后一个目录。例如,用户alice在目录website下进行操作的时候,可能会见到以下命令提示:

        [alice@station website]$

这个提示告诉她,她以用户名“alice”在计算机“station”登录,现在的位置是目录website。但是在系统其他位置可能也有叫做website的目录。这个完全(或绝对)路径可以使用pwd(print working directory)命令显示。

用法:

        pwd

用户alice希望确定她现在所处的正确目录,应该使用pwd。

        [alice@station student]$ pwd
        /home/alice/website

5.更换目录:cd命令

前面说过,如有需要,进程可以改变它们的cwd。这包括bash Shell命令,它提供从命令提示改变现有位置的cd(change directory(改变目录))命令。

用法:

        cd [DIRECTORY]

如果没有指定,DIRECTORY默认为用户主目录。

考虑以下命令:

        [alice@station website]$ pwd
        /home/alice/website
        [alice@station website]$ cd /home
        [alice@station home]$ pwd
        /home
        [alice@station home]$ cd /home/alice/website/songs
        [alice@station songs]$ pwd
        /home/alice/website/songs

我们注意到pwd命令的结果和命令提示的最后一部分都有变化,这反映出执行每个cd命令之后新的cwd。

目录导航是非常重要的,所以会有一些特殊的缩写表示某些特定的目录,如表2-1所示。

表2-1 特殊目录名

我们先在解释一下这个表格中的条目。首先,除了最后一个符号名称以外,不仅在bash Shell的cd命令中,而且在大多数上下文中都可识别这些符号名称。

其次,很多时候我们会用父子的关系类比目录树。如果dir1包括dir2,我们会说dir2是dir1的子目录,dir1是dir2的父目录。所以目录..与cwd相比,离树根更近一层。每一个用户都会有一个指定的主目录,在一般情况下是/home下的一个子目录(在第3章我们会再谈这个问题),并且目录名与他们的用户名相同;“~”代表这个目录。最后,“-”是一个特殊的cd命令选项,指上一个工作目录,可以用它轻易的更换目录。

再考虑以下命令:

        [alice@station songs]$ pwd
        /home/alice/website/songs
        [alice@station songs]$ cd ~
        [alice@station alice]$ pwd
        /home/alice
        [alice@station alice]$ cd -
        [alice@station songs]$ pwd
        /home/alice/website/songs
        [alice@station songs]$ cd ..
        [alice@station website]$ pwd
        /home/alice/website
        [alice@station website]$ cd
        [alice@station alice]$ pwd
        /home/alice

以上例子的最后一部分命令显示,在默认状态下,如果没有指定目录,cd命令会使用目录“~”。

6.绝对引用和相对引用

这一部分讨论确定文件位置的两种方式。在学习这本教程时应该记住,在Linux中,目录也是文件的一种,所以谈到的所有有关文件的命名对目录和常用数据文件也同样适用。

要找到一个文件,我们必须提供足够的信息,才能在文件系统中找到文件的位置。这个位置可以用两种方式表示:绝对引用(绝对路径名)或相对引用(相对路径名)。

绝对引用以斜线(/)开头,然后给出文件的FQN。也就是说,绝对引用列出从“/”到达目标文件需要经过的文件系统目录树的所有分枝。无论你所在的文件系统在何处(也就是说,不考虑cwd的值),绝对引用都可以清楚地标识所有具体名称。在本节中我们已经谈到过几个绝对引用的例子。

相对引用不是描述从“/”到文件的路径,而是起始于当前目录的路径。例如,如果cwd是/home/alice,那么song1.midi的相对引用就可能是website/songs/song1.midi。这是相对引用,因为它不是从“/”开始。这种引用方式只列出从/home/alice开始需要经过的目录,而不是从“/”开始。相对引用必须先列出cwd中的一个目录(或文件)才能有效。

所有Linux目录都包含两个特殊条目:目录 . 和 ..,分别代表当前目录和父目录。因此,前面关于cd命令的讨论里所举的例子,“cd..”其实是一个相对引用。

表2-2列出更多相对引用的例子。这些例子都是FQN为/home/alice/sample.txt文件的引用。有几个例子会故意“绕弯子”。

表2-2 /home/alice/sample.txt的一些相对引用的例子

最后那个例子虽然很笨,但还是正确的。

2.1.2 示例

1.找到你的主目录

用户hogan刚刚登录,他不知道在默认状态下,他的主目录就是他的cwd。他也不知道他的主目录是/home/hogan。他希望找到他的主目录,看他的默认cwd是否真的是他的主目录。

        [hogan@station hogan]$ cd ~
        [hogan@station hogan]$ pwd
        /home/hogan
        [hogan@station hogan]$ cd -
        /home/Hogan

①用户hogan知道cwd以hogan结尾(命令提示告诉他的),但是他不清楚这是不是主目录。他使用cd命令和~目录符号转移到他的主目录。

②然后,用户hogan使用pwd显示他主目录的FQN。他现在知道他的主目录是/home/hogan,但这里是他的出发点吗?

③为了搞清楚他的出发点在哪里,用户hogan再次使用cd命令,这次是回到他的上一个工作目录。

④cd -命令在改变目录后显示cwd(为什么这是合理的做法?)。用户hogan现在知道系统在他登录时将他的主目录作为他最初的工作目录。

2.使用目录树

用户alice需要编辑她网站上的一些html文件。登录后,她需要进入到她主目录下的相关子目录。然后她想到/etc查看配置文件。最后她要回到主目录开始另一项工作。

        [alice@station alice]$ cd website/html
        [alice@station html]$
        ...(编辑html文件)...
        [alice@station html]$ cd /etc
        [alice@station etc]$
        ...(查看配置文件)...
        [alice@station etc]$ cd
        [alice@station alice]$
        ...(继续其他工作)...

①用户alice使用相对路径进入目录/home/alice/website/html,因为它比FQN简短,其实两种方式都是可行的。

②修改好她的html文件后,用户alice使用绝对引用进入目录/etc。在这里,绝对路径比同样的相对路径../../../../etc简短易懂。

③注意:命令提示在目录etc前没有加“/”。默认的bash提示只显示cwd的最后一个目录名。

④完成了在/etc的工作,用户alice使用cd命令的默认行为回到她的主目录。

2.1.3 练习题

所有题目都假设你是已经登录标准教学系统的用户student。

(1)以下哪一项是相对目录引用?( )

A./home/student

B./etc

C...

D.~

(2)pwd可以显示以下哪一项?( )

A.home/student

B./etc

C...

D.~

(3)执行cd ~命令后再执行pwd,最可能的结果是什么?( )

A./home/student

B./etc

C...

D.~

你的屏幕会显示以下内容:

        [student@station html]$ cd ../bin
        [student@station bin]$ pwd
        /home/student/bin
        [student@station bin]$ cd -

(4)pwd的输出结果是什么?( )

A./home/student

B./home/student/html

C./home/html

D.-

(5)以下哪一对命令的作用是一样的?( )

A.cd .. 和cd-

B.cd / 和cd root

C.cwd和pwd

D.cd ~ 和cd

2.2 重要目录

主要概念

➢ 每个用户都会有指定的主目录。

➢ /tmp目录为通用临时空间。

➢ /bin和/usr/bin目录放置常用的可执行文件。

➢ /etc目录包含系统配置文件。

➢ 不要将根用户的主目录“/root”和文件系统根目录“/”混淆。

2.2.1 讲义

1.标准Linux目录结构

Linux可以支持多种计算机系统,包括服务器、开发工作站、个人台式机系统等。为了统一这些不同系统的文件系统目录结构,大多数Linux系统使用统一的命名和使用标准,使系统更容易使用和维护。使用第2.1节提到的树形图,目录树第一层的一部分可能如图2-7所示。

图2-7 从/开始的部分目录树

本节将简单(有时会非常简单地)介绍这里每个目录的作用。

2.用户主目录

每个Linux系统用户都会有一个指定的特殊目录,叫做他们的主目录(home directory),这是他们在系统中的“私人”空间。通常这是一个在目录/home下的子目录,它的目录名与用户登录时使用的用户名一致(第2.1节提到的/home/alice和/home/hogan就是例子)。这里有一个例外就是超级用户(或叫做根用户),他的主目录通常是/root。对于其他用户来说,当波浪号(~)是文件或目录引用的第一个符号时,代表此用户的主目录的FQN。

用户主目录显著的作用是作为私人数据空间,他们可以用这个空间把他们的文件与其他用户的文件分开保存。通常用户可在他们的主目录下自由创建子目录(在配额限制之内)并整理他们的数据。因为每个用户都有自己的空间,所以两个用户可以将文件或目录取同样的名字而不会出现问题。例如,用户alice和用户hogan都可以在他们各自的目录中建立名为public_html的文件,而全名分别为/home/alice/public_html和/home/hogan/public_html。将每个用户的空间与其他用户分开,也更容易保证用户资料的安全。

用户主目录的另一个显著作用是保存用户特有的配置文件。比如说,用户blondie登录时,她所需的环境可能与用户prince所需的环境不同。用户blondie可能会喜欢使用不同的屏幕颜色、不同的简写命令,或是与用户prince完全不同的桌面环境。用户特有的本地配置文件可以做到这些。在默认状态下,当生成用户账户后,或者首次使用某个特定的系统资源时,系统就会自动生成许多类似的配置文件。

一般来说,用户可以在一定程度上完全控制他们的主目录,但访问系统的其他部分则会受到限制。比如,在通常情况下,即使用户alice可以读取目录/etc下的任何配置文件,但是不能对这些文件进行修改或删除。她也不太可能读取、修改或删除系统其他用户目录下的文件。

用户登录系统的时候,会“进入”他们的主目录,也就是说,系统将其最初的工作目录作为他们的主目录。

3.临时目录/tmp

除了自己的主目录,用户还可以使用目录/tmp中共享的“scratch(临时)”空间。一个数据压缩程序可能会将一部分的结果保存在目录/tmp中,只在工作完成后将最后结果放在用户主目录中。Linux系统通常会分配一定的配额给用户,以防止任何一个用户过度占用有限空间。如果用户暂时需要一些额外空间,他可以使用目录/tmp,而不需要占用自身的配额。这一点特别重要,因为用户并不总是很清楚一个服务需要占用多少空间,而有些服务(如X)如果没有临时存储空间就根本无法运行。系统的所有进程和用户都可以使用这个“通用”的临时空间。系统在几天后会自动删除这个目录中的文件。

4.配置目录/etc

Linux系统的特点之一是它的灵活性。通过修改配置文件,可以控制系统的任何方面。配置文件一般保存在配置目录/etc或它的子目录中。例如经常用来作为邮件服务器的sendmail程序就使用保存在目录/etc/mail中的配置文件。系统启动脚本位于/etc/rc.d,网络配置文件位于目录/etc/sysconfig中。很明显,一般用户是不能修改目录/etc中的文件的(在有些情况下,甚至不能读这些文件),但是系统管理员会经常使用这些文件管理系统。

5.命令目录/bin和/usr/bin

大部分系统命令都以机器可读格式保存为二进制文件。一般用户使用的命令通常位于二进制目录/bin或/usr/bin中。系统必需的核心工具命令如ls、cd、cp、mv和文本编辑器vi都位于目录/bin中。辅助工具如编译器、网页浏览器和办公工具软件位于目录/usr/bin中,这些目录下的工具也可以通过网络共享给其他系统上的用户使用。我们可以将 /bin和/usr/bin当成非特权命令目录,因为用户不需要有任何特权就可以使用其中的命令。

6.命令目录/sbin和/usr/sbin

就如同目录/bin和/usr/bin为一般用户保存命令文件一样,它们也为超级用户(根用户)保存命令文件。其中包括安装和删除硬件、启动和关闭系统以及进行系统维护的命令。和上面提到的将命令分别存放于/bin和/usr/bin的原因一样,这些特权命令也是分别保存在两个目录中。

7.可变目录/var

位于目录/bin或/etc中的命令和配置文件基本上是不变的。这些文件通常都很稳定,而另外一些文件则会经常变化。这些文件包括收发的电子邮件、系统日志、新闻组、网站、ftp归档文件等。这些内容经常变化的文件和目录通常位于变量目录/var中。将这些文件放在这里便于给它们分配空间,同时也保护系统里其他比较稳定的文件。

8.root vs. /root vs. /(文件系统根)

root(根)这个词在Linux中意义重大但又十分容易混淆。“root”是超级用户的用户名,此用户在系统中有至高无上的权力。同时它也是这个用户的主目录/root。它还是文件系统目录树的根目录。通常我们可以根据上下文判断它的含义,但是有些词汇如“根目录”,它的意义就不是很清楚。沟通时请考虑到这一点,尽量避免造成混淆。如果从上下文判断不出它的意思,则要尽量想办法澄清。

2.2.2 示例

1./tmp目录

用户alice刚刚知道有些进程会自动使用/tmp目录,她想看一下刚才做的工作有没有用到这一空间,同时测试她是否真的可以在这一空间中创建文件。

用户alice使用touch命令建立一个文件。

        [alice@station alice]$ cd /tmp
        [alice@station tmp]$ ls
        orbit-alice   ssh-XXDg4ke3
        [alice@station tmp]$ ls -l
        total 8
        drwx------   2 alice   alice       4096 Mar 16 08:04 orbit-alice
        drwx------   2 alice   alice       4096 Mar 16 07:07 ssh-XXDg4ke3
        [alice@station tmp]$ touch newfile
        [alice@station tmp]$ ls -l
        total 8
        -rw-rw-r--   1 alice   alice          0 Mar 16 14:14 newfile
        drwx------   2 alice   alice       4096 Mar 16 08:04 orbit-alice
        drwx------   2 alice   alice       4096 Mar 16 07:07 ssh-XXDg4ke3

①进入/tmp目录后,用户alice使用ls命令和ls -l命令浏览目录/tmp中的内容。虽然这里有许多由ls -l命令列出的文件她都不认识,但是她能看到她的用户名多次出现,由此相信她运行的一些程序在目录/tmp中留下一些文件。其实orbit-alice和ssh-XXDg4ke3这两个文件是她在启动桌面时产生的。

②用户alice使用touch命令在目录/tmp中建立了一个名为newfile的新的空文件。和许多Linux命令一样,touch命令在完成后屏幕上没有显示。用户alice使用另一个ls -l命令证实touch命令执行成功。

2.在目录/bin和/usr/bin中搜寻命令

用户hogan想知道能否在二进制命令目录/bin或/usr/bin中找到他通常使用的一些命令,包括cp、firefox、cd和fdisk。

用户hogan可以使用ls命令搜寻这些命令,但他想尝试使用一个新的命令which。

简单用法:

        which PROGRAM

用户执行这一命令时显示使用的PROGRAM命令文件的FQN。

        [hogan@station hogan]$ which cp ①
        /bin/cp
        [hogan@station hogan]$ which firefox ②
        /usr/bin/firefox
        [hogan@station hogan]$ which cd ③
        /usr/bin/which: no cd in (/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/hoga
        n/bin:)
        [hogan@station hogan]$ which fdisk ④
        /usr/bin/which: no fdisk in (/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/h
        ogan/bin:)
        [hogan@station hogan]$ ls /sbin
        ...
        fdisk               pivot_root
        findfs              plipconfig
        firmware_helper     portmap
        fixfiles            poweroff
        fsck                pppoe
        fsck.cramfs         pppoe-relay
        ...

①用户hogan看到cp位于目录/bin中,对他来说这是合理的,因为目录/bin中的文件都应该是一般用户在系统中用得到的文件。

②用户hogan在目录/usr/bin中找到了firefox(他使用的网络浏览器)。这也是合理的,因为目录/usr/bin中的文件应该是用户需要但不一定现成的文件。

③用户hogan很惊讶,因为结果显示系统中没有cd这一命令。他以为会有/bin/cd的答复。(为什么?)用户hogan不知道cd是Shell内部命令的一种,由bash Shell命令本身提供。另外他还可以在目录/bin里找到bash。

④用户hogan对于fdisk命令的结果也很惊讶。他知道这是一个既重要又危险的磁盘分区命令,应该只有超级用户才可以使用,他认为这个命令会在/sbin目录中。但仔细一看,他发现which命令并没有在/sbin目录里寻找fdisk命令。他使用ls命令在/sbin目录里查看,确认fdisk命令的位置和他的想法一样。以后用户hogan会学到的命令路径(command path)概念可以解释这一现象。

2.2.3 练习题

(1)下列哪一个最“不可能”是用户的主目录?( )

A./home/student

B./root

C./

D.以上都不可能是主目录

(2)文件named.conf是一个系统配置文件,它位于( )

A./tmp

B./etc

C./bin

D./sbin

(3)文件e2fsck是系统随时都可以使用的特权命令,它位于( )

A./tmp

B./etc

C./bin

D./sbin

(4)/root目录很重要是因为( )

A.它是Linux文件系统的根目录

B.它是超级用户的主目录

C.它可被缩写为~

D.任何用户都不能阅读它的内容。

(5)以下哪一条命令“不能够”用来在目录/tmp中创建文件?( )

A.touch /newfile

B.touch /tmp/newfile

C.touch ../newfile

D.touch ../tmp/newfile

(6)是非题:/bin和/usr/bin含有同样的文件。( )

A.是

B.否

(7)是非题:只有根用户才能阅读目录/etc中的文件。( )

A.是

B.否

(8)是非题:网页文件一般位于目录/var中。( )

A.是

B.否

(9)是非题:将用户账户个人化的配置文件位于/etc/users.d。( )

A.是

B.否

(10)是非题:X使用/tmp。( )

A.是

B.否

2.3 文件管理

主要概念

➢ 使用Shell重定向创建(或追加写入)文件。

➢ cp命令复制文件。

➢ mv命令移动文件。

➢ rm命令删除文件。

➢ 重定向、移动或复制可能“损坏”文件。

2.3.1 讲义

1.重定向(redirection)

许多命令产生“可见”输出,即输出结果可以显示在屏幕上。比如说,用户julius见到的pwd命令输出结果显示为:

        [julius@station julius]$ pwd
        /home/julius
        [julius@station julius]$

Linux系统将所有的项目都当作文件处理。在上述例子中,pwd命令将输出传送到“标准输出(standard output)”文件,也就是STDOUT,这是用户登录系统所用的默认屏幕(例如,显示器)。

bash命令Shell的一个特征是,它通常可以将通过STDOUT显示到屏幕的输出“重定向”到其他文件,使用特殊重定向符号“>”就可以做到。

        [julius@station julius]$ ls
        [julius@station julius]$ pwd > results.txt
        [julius@station julius]$ ls
        results.txt

这里另建了文件results.txt,并将命令的输出重定向到这个文件。另一个可以帮助我们检查这一结果的有用命令是cat命令(concatenate)。

用法:

        cat [OPTIONS] [FILE...]

它将FILE内容显示至标准输出。

cat命令将复制标准输出中列出的所有文件。如果有一个以上的文件,这样做就可以简单地连接文件。和其他命令一样,这个输出默认会被显示在屏幕上,但也可以被重定向到另一个文件。我们会用这个命令显示一个文件的内容,而不是重定向结果。

        [julius@station julius]$ pwd > results.txt
        [julius@station julius]$ ls
        results.txt
        [julius@station julius]$ cat results.txt
        /home/julius

这次用户julius将pwd命令输出的结果重定向至results.txt文件,然后使用cat命令显示。

如果这个文件已经存在,重定向将会删除并重建一个空的文件存放输出结果。但是,如果使用双箭头(>>),新的输出结果将会追加在文件末尾。如果使用“>>”,但目标文件不存在的话,系统将会建立一个文件,这跟使用“>”的情况一样。“>”是Shell元字符之一,也就是说,这个符号对于bash Shell命令有特殊意义,它会在执行其他命令前解读这一符号。类似需要注意的符号还有很多,在以后的章节中我们还会提到。

产生可见输出的最简单的命令是echo命令。这一命令将所有键盘输入的文本作为命令的一部分回显给STDOUT(一般作为显示)。用户可以将这一命令和重定向命令结合使用创建文本文件。

用法:

        echo [OPTIONS] [STRING...]

回显字符串(STRING)至标准输出。

示例:

        [julius@station julius]$ echo Hello > greetings.txt
        [julius@station julius]$ echo How are you >> greetings.txt
        [julius@station julius]$ cat greetings.txt
        Hello
        How are you

示例:

        [julius@station julius]$ ls
        [julius@station julius]$ pwd > results.txt
        [julius@station julius]$ cat results.txt
        /home/julius
        [julius@station julius]$ ls >> results.txt
        [julius@station julius]$ cat results.txt
        /home/julius
        results.txt

2.使用cp复制文件

可以使用cp(copy)命令复制文件。

用法:

        cp [OPTIONS] {SOURCE} {TARGET}
        cp [OPTIONS] {SOURCE...} {DIRECTORY}

第一种形式可将SOURCE文件复制为TARGET。第二种形式可以将一个或多个文件复制到某个目录中。文件SOURCE被复制到DIRECTORY目录中,称为DIRECTORY/SOURCE, DIRECTORY/。用户也可以同时复制整个子目录树(可使用man cp命令查看帮助,具体方法在此不予讨论)。

示例:

(1)复制文件mysong.midi,将复制文件命名为backup.midi:

        cp mysong.midi backup.midi

(2)复制mynovel.txt到/tmp目录下做一个备份:

        cp mynovel.txt /tmp

新文件名为/tmp/mynovel.txt。

(3)复制文件songs.tar和novels.tgz到/tmp目录下:

        cp songs.tar novels.tgz /tmp

新文件名为/tmp/songs.tar和/tmp/novels.tgz。

(4)从你的主目录复制文件webpage.html到当前目录:

        cp ~/webpage.html .

新文件名为 ./webpage.html。

3.使用mv移动或重新命名文件

使用mv(move)命令可以将文件从一个目录移动到另一个目录,或重新命名文件。

用法:

        mv [OPTION...] {SOURCE} {TARGET}
        mv [OPTION...] {SOURCE...} {DIRECTORY}

第一种形式将SOURCE文件重新命名为TARGET。第二种形式可以将一个或多个文件同时移动到某个目录下。文件SOURCE被移动到DIRECTORY中,重新命名为DIRECTORY/SOURCE。如果SOURCE是目录的话,那么移动或重新命名的就是目录。

mv命令突出了Linux系统的一个重要特征,它将文件的“名字”和“内容”完全分开。虽然mv命令的名称源于“move(移动)”,但它并不是真的移动数据,文件系统只是记录文件名的更改。如果文件名从/somedir/somefile改为/somedir/newname,这是文件“重新命名”。如果文件名从/somedir/somefile改为/newdir/somename,这是文件“移动”。如果文件名从/somedir/somefile改为/newdir/newname,这是同时“重新命名”和“移动”。对Linux系统来说,这些都是一样的,都是更改文件的FQN。

示例:

(1)将文件mysong.midi重新命名为backup.midi:

        mv mysong.midi backup.midi

(2)将文件mynovel.txt移动到/tmp目录下:

        mv mynovel.txt /tmp

新文件名为/tmp/mynovel.txt。

(3)将文件songs.tar和novels.tgz移动到/tmp目录下:

        mv songs.tar novels.tgz /tmp

新文件名为/tmp/songs.tar和/tmp/novels.tgz。

(4)将文件webpage.html从你的主目录移动到当前工作目录中:

        mv ~/webpage.html .

新文件名为 ./webpage.html。

(5)将当前工作目录中的子目录html重新命名为public_html:

        mv html public_html

假设./public_html不存在,这样做将 ./html重新命名为 ./public_html,比较下例。

(6)你的cwd是你的主目录,它下面有两个子目录,~/images和~/html。将目录images移动到目录html:

        mv images html

新目录称为~/html/images。你可能会注意到此例和上例的相似之处。它们之间的主要不同为:在这个例子中目标目录~/html已经存在,所以mv命令将原来的目录移动到目标目录“中”(目标目录“下”)。上个例子中,目标目录原来不存在,所以mv命令将原来的目录重新命名。

4.使用rm命令清除(删除)文件

可以使用rm(remove)命令清除(擦除、删除)文件。

用法:

        rm [OPTIONS] {FILE...}

将FILE从文件系统中删除。严格地说,这只是将FILE从文件系统中“分离(unlink)”,我们以后还会解释这一定义。与合适的选项一起使用,这个命令也可以同时删除整个子目录树(可使用man rm命令获得该操作方法的详细信息)。

除非使用特殊命令选项,否则rm命令不能删除目录。另有rmdir命令完成这一工作。

Note

除非使用特殊命令选项,否则rm命令不能删除目录。另有rmdir命令完成这一工作。

Warning

是的,rm命令“可以”同时删除整个目录树。如果不小心的话,超级用户可能会使用这一命令一次删除文件系统的“全部”内容。

Warning

rm的文档包括以下声明:“如果使用rm命令删除文件,文件内容可以复原。”但这样的复原要求此课程以外更专业的知识,所以在实际操作中要将此命令作为不可逆的执行命令。

示例:

(1)删除mysong.midi:

        rm mysong.midi

(2)删除songs.tar和novels.tgz:

        rm songs.tar novels.tgz

(3)从你的主目录中删除photos.html:

        rm ~/photos.html

5.文件损坏

在前面部分的警告中提到了一些命令如cp、mv和rm的危险性。但这些只是冰山一角,像Linux这样强大的系统势必还有很多潜在的危险。下面我们就来讨论其中之一:文件损坏。

使用“>”重定向、cp和mv命令都能够命名目标文件。在一般情况下,这些命令创建这些新文件并命名。但如果重定向、cp或mv命令的目标是已经存在的文件,在事先“没有”给出警告的情况下这些文件就会被损坏。我们用以下几个示例来讨论这个问题。

示例:

        [julius@station julius]$ pwd > file1
        [julius@station julius]$ cat file1
        /home/julius
        [julius@station julius]$ ls > file1
        [julius@station julius]$ cat file1
        mycwd

如果你仔细观察就会发现,第二个重定向在没有给出提示的情况下就更换了file1的内容。文件file1已经被损坏了。

示例:

        [julius@station julius]$ touch file1
        [julius@station julius]$ ls
        file1
        [julius@station julius]$ pwd > file2
        [julius@station julius]$ ls
        file1  file2
        [julius@station julius]$ cat file2
        /home/julius
        [julius@station julius]$ mv file2 file1
        [julius@station julius]$ ls
        file1
        [julius@station julius]$ cat file1
        /home/julius

你还会发现mv命令没有给出警告就更换了file1的内容,文件file1又被损坏了。cp命令会以同样的方法替换文件file1。

要完全理解下个示例,我们需要更多地了解重定向,特别是重定向在“什么时候”发生。

示例:

        [julius@station julius]$ touch file1
        [julius@station julius]$ ls
        file1
        [julius@station julius]$ ls > file2
        [julius@station julius]$ ls
        file1  file2
        [julius@station julius]$ cat file2
        file1
        file2

第一个ls命令只显示file1,为什么file2会显示file1“和”file2呢?答案是:这些命令执行的顺序导致这种结果。第一步,bash命令重定向文件file2时创建一个新文件(见前面对重定向的讨论)。第二步,ls命令产生文件列表,显示原来的文件file1和新建的文件file2。第三步,ls命令的输出被传送到file2。

示例:

        [julius@station julius]$ pwd > mycwd
        [julius@station julius]$ cat mycwd
        /home/julius
        [julius@station julius]$ cp mycwd mycwd
        cp: `mycwd' and `mycwd' are the same file
        [julius@station julius]$ cat mycwd
        /home/julius
        [julius@station julius]$ cat mycwd > mycwd
        cat: mycwd: input file is output file
        [julius@station julius]$ cat mycwd
        [julius@station julius]$

这个示例需要一些解释。首先,用户julius使用pwd命令创建文件mycwd,然后使用cat命令显示其内容。他试图使用cp对文件本身进行复制,cp察觉到这个“错误”,于是显示错误信息,并未执行(mv命令也会这样做)。下一行的cat命令检查出mycwd没有改变。这些都是我们知道的,但下面一系列命令的结果却出人意料。用户julius使用cat命令和重定向操作同一文件。同样的,cat命令指出源文件和目标文件相同,没有执行。但是最后用cat命令检查文件mycwd没有结果。文件内容丢失了!为什么会出现这样的情况呢?这是因为命令执行的顺序。第一步,bash命令重定向到现有文件时会删除原有文件重建一个空的新文件(见前面对重定向的讨论)。第二步,现在执行cat命令是没有意义的,因为源文件mycwd已经被损坏并重建。错误已经无法挽回了。

有一些命令选项和特殊的命令Shell功能可以以某种形式减少这种错误的发生,但这些不是本章所要讨论的内容。这是“功能”不是“错误”,需要更好了解才能正确使用。

2.3.2 示例

1.移动和存档简单网站

用户madonna想要建立一个简单的个人网站,但她的ISP告诉她说所有的网页文件都放在错误的目录中,这些文件应该放在目录~/public_html下而不是目录~/html下。她需要将文件移动到正确的目录中,同时她还希望将旧目录备份一份到目录archive下,以防万一。archive是已经存在的目录。

        [madonna@station madonna]$ ls
        html   archive
        [madonna@station madonna]$ mv html public_html
        [madonna@station madonna]$ cd public_html
        [madonna@station public_html]$ ls
        index.html  photo.jpeg
        [madonna@station madonna]$ cp index.html photo.jpeg ../archive

用户madonna只要重新命名目录就可以移动所有文件。她需要使用cp命令同时复制一个以上的文件,从而进行备份。

2.移动简单网站

用户nero想要建立一个简单的个人网站,但他的ISP告诉他说所有的文件都放错目录了,应该放在目录~/public_html下而不是他的主目录下。他需要将文件移动到正确的目录中。但他的问题要比用户madonna的复杂,他不能直接重新命名子目录。目录public_html是他的ISP为他建立的。

        [nero@station nero]$ ls
        index.html  photo1.jpeg  photo2.jpeg  public_html
        [nero@station nero]$ mv index.html photo1.jpeg photo2.jpeg public_html
        [nero@station nero]$ ls
        public_html
        [nero@station nero]$ cd public_html
        [nero@station public_html]$ ls
        index.html  photo1.jpeg  photo2.jpeg

用户nero使用mv命令同时移动一个以上的文件。

3.删除robots.txt

用户Elvis注意到在他的~/public_html目录中有一个他不知道的文件robots.txt。他决定删除它。

        [elvis@station elvis]$ ls
        public_html
        [elvis@station elvis]$ ls public_html
        index.html  robots.txt
        [elvis@station elvis]$ rm public_html/robots.txt
        [elvis@station elvis]$ ls public_html
        index.html

2.3.3 练习题

(1)复制文件的命令是( )

A.dupe

B.rep

C.copy

D.cp

(2)将文件file1.txt复制到file2.txt,你可以使用( )

A.cp file1.txt > file2.txt

B.cp file1.txt file2.txt

C.dupe file1.txt file2.txt

D.mv file1.txt file2.txt

(3)命令mv f1 f2 f3 f4可以做到( )

A.将四个文件从当前目录中移出

B.将四个文件移动到当前目录C.将四个文件移动到默认目录

D.将三个文件从当前目录中移出

(4)将file1从当前目录中删除,可以使用( )

A.rm file1

B.erase file1

C.del file1

D.cut file1

(5)在以下哪种情况下cp file.a file.b会损坏file.b?( )

A.file.a是一般文件

B.file.a不是空文件

C.file.b是一般文件

D.file.b是目录

(6)如果/home/student是一个目录,那么命令rm /home/student有什么效果?( )

A.将目录中所有文件删除

B.将目录从文件系统中删除

C.删除用户student的账户

D.产生错误信息

(7)命令echo file.1 file.2会( )

A.将file.1复制到file.2

B.在标准输出显示file.1和file.2内容

C.产生错误信息,因为没有重定向符号

D.在标准输出显示“file.1 file.2”

(8)命令ls > file.1会( )

A.产生错误信息,因为>是无保护Shell命令元字符

B.将ls命令的一般输出添加到file.1中

C.替换现有文件file.1

D.如果file.1已经存在,命令不能执行

(9)如果item.1和item.2已经存在,在什么情况下命令mv item.1 item.2能够移动整个子目录树。( )

A.item.1和item.2是现有子目录

B.只在使用特殊命令选项时

C.只有在item.2是空的时候

D.只有在item.1是空的时候

(10)命令cp item.1 item.2能够复制整个子目录树,如果:( )

A.item.1和item.2是已存在的子目录

B.必须使用特殊命令选项

C.只有在item.2是空的时候

D.只有在item.1是空的时候

2.4 目录管理

主要概念

➢ 使用ls -R命令查看目录树全部内容。

➢ mkdir命令建立目录。

➢ rmdir命令删除(清空)目录。

➢ cp -r递归复制目录。

➢ rm -r递归删除目录。

2.4.1 讲义

1.建立(新的、空)目录:mkdir

要将文件组织在目录里,必须先建立你需要的目录。在Linux系统中,建立新目录的命令是mkdir(make directory)。

用法:

        mkdir [OPTIONS] {DIRECTORY...}

如果没有DIRECTORY(目录)存在,那么就建立目录,如果已经存在一个或者多个目录,会产生错误信息,但还会继续建立尚未存在的新的目录。

用户Elvis会这样建立子目录~/public_html:

        [elvis@station elvis]$ ls
        [elvis@station elvis]$ mkdir public_html
        [elvis@station elvis]$ ls
        public_html

用户Elvis然后可以为public_html建立子目录:

        [elvis@station elvis] ls public_html
        [elvis@station elvis] mkdir public_html/images
        [elvis@station elvis] ls public_html
        images

注意

在默认状态下,如果父目录不存在,mkdir命令不能为其建立子目录:

            [elvis@station elvis] ls work
            ls: work: No such file or directory
            [elvis@station elvis] mkdir work/spreadsheets
            mkdir: cannot create directory `work/spreadsheets': No such file or directory

如果用户Elvis使用mkdir -p(parent)命令,他可以一次建立整个目录树:

        [elvis@station elvis] ls work
        ls: work: No such file or directory
        [elvis@station elvis] mkdir -p work/spreadsheets
        [elvis@station elvis] mkdir -p work/images/logos
        [elvis@station elvis] mkdir -p work/images/advertising
        [elvis@station elvis] ls work
        images  spreadsheets
        [elvis@station elvis] ls work/images
        advertising  logos

2.列表显示目录树

你知道当ls命令附加一个目录作为其参数时,能列出整个目录的内容。但如果这个目录还包含其他目录呢?在默认状态下,ls命令只显示上层目录内容。如果你希望ls命令显示子目录,要在这个命令后加-R作为命令行选项。

如果命令在一个结构(目录)里执行的时候,它对这一结构里的每个项目(子目录或文件)的处理都和它对顶层项目的处理相同,这种执行方式叫做递归执行(recursively)。在ls命令后添的加命令行选项-R指示命令递归列出目录内容。

举例来说,用户hogan在查看机器的网络配置时,他认为目录/etc/sysconfig/networking可能非常重要。用户hogan递归列出这目录中的文件和子目录,查看其内容。

        [hogan@station hogan]$ ls -R /etc/sysconfig/networking/
        /etc/sysconfig/networking/:
        devices  ifcfg-lo  profiles
        /etc/sysconfig/networking/devices:
        ifcfg-eth0
        /etc/sysconfig/networking/profiles:
        default  netup
        /etc/sysconfig/networking/profiles/default:
        hosts  ifcfg-eth0  network  resolv.conf
        /etc/sysconfig/networking/profiles/netup:
        hosts  ifcfg-eth0  network  resolv.conf

ls–R命令还可以和我们以前学过的命令行选项一起使用,如ls–sR命令可显示文件大小;ls–lR命令可列出文件属性。

3.删除(清空)目录:rmdir

删除目录的命令是rmdir(remove directory)命令。

用法:

        rmdir [OPTIONS] {DIRECTORY...}

如果目录是空的,此命令会删除它们,如果目录中有内容,则会产生错误信息且不能删除目录,但是它会继续删除其余的空目录。注意,只包括一个子目录的目录不是空的。

用户Elivs希望删除他的子目录~/public_html/images,他会进行如下操作:

        [elvis@station elvis]$ ls
        public_html
        [elvis@station elvis]$ rmdir public_html/images
        [elvis@station elvis]$ ls
        [elvis@station elvis]$

我们注意到命令如mkdir和rmdir以静默形式完成。

4.复制目录树:cp -r

第2.3节介绍cp命令的时候我们说过,这个命令加带一些选项可以复制整个目录树。在这里我们介绍其中一个选项:-r(recursive)。(许多命令都有递归选项,能够访问目录树的所有分枝,并依次对其进行处理。)

如图2-8所示的是用户hogan的主目录的结构:

图2-8 复制前的目录结构

可以用下面的简单指令复制这个目录树中的所有众多分枝和文件,所得的目录结构如图2-9所示:

图2-9 复制后的目录结构

请记住,当cp命令最后的参数是一个已经存在的目录时,文件会被复制在这个目标目录下。上个例子中的目录archive之前不存在,在复制的过程中将创建这个目录。但如果目录archive是一个已经存在的目录,结果会不同。

图2-10 复制前的目录结构

用户hogan使用同样的命令复制,所得的目录结构如图2-11所示:

图2-11 使用cp -r website archive复制后的目录结构

在第二个例子里,在目录archive中重建了目录website。

5.删除目录树:rm -r

第2.3节介绍rm命令的时候我们说过,这个命令加带一些选项可以删除整个目录树。这跟cp命令使用的选项相同,即-r(recursive)选项。

如图2-12所示的是用户hogan的主目录结构:

图2-12 删除前的目录结构

用户hogan使用一个命令删除分枝media,删除后的目录结构如图2-13所示:

图2-13 删除后的目录结构

这里我们要再强调一次:一般来说,删除操作是不可逆的。因此随意使用rm -r命令是很危险的。

2.4.2 示例

1.为目录树做备份

用户hogan有一份重要的报告,他将其中的几份文件放在目录report下的子目录里。

        report/
        |-- chapter01/
        |   |-- figures/
        |   |   |-- image01.png
        |   |   `-- image02.png
        |   |-- section01.html
        |   `-- section02.html
        `-- chapter02/
            |-- figures/
            |   |-- image01.png
            |   `-- image02.png
            |-- section01.html
            `-- section02.html
        4 directories, 8 files

他想使用自动拼写检查功能检查和更正拼写错误。这是他第一次使用这个工具,在进行前,他希望先将他的工作备份。他先使用cp命令备份文件。

        [hogan@station hogan]$ cp report report.bak
        cp: omitting directory `report'

意识到他的错误,他添加了命令行选项-r,让cp命令递归复制。

        [hogan@station hogan]$ cp -r report report.bak

目录report中的内容被递归复制到report.bak里。

        .
        |-- report/
        |   |-- chapter01/
        |   |   |-- figures/
        |   |   |   |-- image01.png
        |   |   |   `-- image02.png
        |   |   |-- section01.html
        |   |   `-- section02.html
        |   `-- chapter02/
        |       |-- figures/
        |       |   |-- image01.png
        |       |   `-- image02.png
        |       |-- section01.html
        |       `-- section02.html
        `-- report.bak/
            |-- chapter01/
            |   |-- figures/
            |   |   |-- image01.png
            |   |   `-- image02.png
            |   |-- section01.html
            |   `-- section02.html
            `-- chapter02/
                |-- figures/
                |   |-- image01.png
                |   `-- image02.png
                |-- section01.html
                `-- section02.html
        10 directories, 16 files

用户hogan完成拼写检查后,他希望删除备份的目录report.bak。他先使用rmdir命令。

        [hogan@station hogan]$ rmdir report.bak/
        rmdir: `report.bak/': Directory not empty

意识到rmdir命令只能用在清空的目录上,他改用rm -r命令。

        [hogan@station hogan]$ rm -r report.bak/
        [hogan@station hogan]$ ls
        report

2.建立文件的本地副本

用户ventura对程序语言Python感兴趣。他在目录/usr/share/doc/pygtk2-2.10.1/examples/中发现了一个该语言的脚本样本。他希望可以修改这个脚本,以便试一些他的新想法,他没有这个文件的写入权限,于是他决定为这个脚本建立一个本地副本。

      [ventura@station ventura]$ cp -r /usr/share/doc/pygtk2-2.10.1/examples/ .①
      [ventura@station ventura]$ ls -R examples/ ②
      examples/:
      atk    gobject  ide       Makefile.am  pango      simple
      glade  gtk      Makefile  Makefile.in  pygtk-demo
      examples/atk:
      atk-demo.py
      examples/glade:
      autoconnect.py  README      test.glade
      glade-demo.py   test2.glade
      examples/gobject:
      editable-interface.py  properties.py  signal.py
      ...

①在目录名里使用“.”代表“当前目录(local directory)”。cp命令获得一个目录作为它的目的地(最后的参数),会将文件复制到该目录中,并保留原文件名。在这里,目录examples被复制在目录“.”里。

②ls -R命令递归列出所有在目录examples中新建的文件。

现在ventura有了一份Python脚本的本地副本,他可以随意修改它们。

2.4.3 练习题

(1)以下哪个命令会递归列出目录report中的内容?( )

A.lsdir report

B.ls --recur report

C.ls -r report

D.ls -R report

E.ls report \r

用户hogan执行以下命令

        [hogan@station hogan]$ cp rep1.txt rep2.txt rep3.txt reps

(2)在以下哪种条件下,这个命令才能成功执行?( )

A.文件rep1.txt必须是文本文件

B.文件rep1.txt必须是已经存在的目录

C.文件reps必须是已经存在的目录

D.文件rep1.txt、rep2.txt和rep3.txt必须是已经存在的目录

E.命令无法执行,因为使用多重参数的时候,必须加带命令行选项-r。

(3)以下哪个命令建立新的空目录?( )

A.md

B.nd

C.mkdir

D.newdir

E.touch -d

在他的主目录里,用户hogan有一个含有多个文件和子目录的、名为website的目录,他还有一个名为archive的空目录,如下图所示:

下面的问题假设当前工作目录是用户hogan的主目录/home/hogan。

(4)命令cp -r website archive的结果是什么?( )

A.目录archive会被损坏,并由目录website的副本代替

B.目录archive中新建一个名为website的子目录

C.错误,cp命令不能在目录上执行

D.错误,因为-r不是cp命令的选项

E.以上都不是

(5)命令cp website archive/website.bak的结果是什么?( )

A.目录archive中有一个新建的子目录,名为website.bak

B.错误,因为目录archive/website.bak不存在

C.错误,因为复制目录的时候必须加带命令行选项-r

D.错误,应该使用命令cpdir

E.以上都不是

(6)命令mv -r website archive的结果是什么?( )

A.目录archive会被损坏,并由目录website代替

B.目录archive含有新建子目录website

C.错误,因为不能在目录上执行mv命令

D.错误,因为mv命令不能识别命令行选项-r

E.以上都不是

(7)以下哪个命令可以将目录website/media及其子目录移动到目录archive/media中?( )

A.mv -r website/media archive/media

B.mv website/media archive/media

C.mv website/media archive

D.B和C

E.以上全可以

(8)以下哪个命令可以删除目录website/media及其子目录?( )

A.rmdir website/media

B.rm website/media

C.rm -r website/media

D.A和C

E.以上全可以

(9)以下哪个命令可以复制目录website及除website/media/photos之外的子目录?( )

A.cp -x photos website archive

B.cp -d2 website archive

C.cp -x photos website archive/website

D.cp -d2 website archive/website

E.以上都不是

(10)为什么有人会使用rmdir命令,而不使用rm–r命令?( )

A.保证目录中没被注意到的文件不会被在无意中删除

B.因为rmdir命令不需要命令行选项就可以递归执行

C.rmdir命令自动为它删除的文件备份

D.B和C

2.5 文件名和文件名匹配

主要概念

➢ 文件名可以包括“/”外的任何字符。

➢ 用户可以用 / 以外的任何字符,但不代表应该这么做。

➢ 由“.”开头的文件为“隐藏”文件。

➢ *、?、[...] 和 [^...] 符号可以用来匹配文件名,通称“文件名匹配(file globbing)”。

2.5.1 讲义

1.文件名

许多操作系统都限制文件名字符长度的选择和数目。Linux系统允许文件名使用任何可打印的字符,文件名可为任何长度。

不包括目录组成部分,Linux文件名最长可达255个字符。当用在命令里的时候,绝对或相对引用,包括目录组成部分,最长可达4095个字符!这样一来,文件和目录的名称可以极具描述性。

Linux文件名可以包含除“/(斜线)”以外的任何可打印(甚至不可打印)字符。不能使用斜线是因为,它是用来在相对引用或FQN中分开目录名组成部分的符号。因为很多“不常用”符号是Shell的元字符,所以在文件名中使用这些符号时要用引号保护。

        [julius@station julius]$ touch 'a and b'
        [julius@station julius]$ touch '"'
        [julius@station julius]$ touch "'"
        [julius@station julius]$ touch '!@#$%^&*()_+=-|\}]{[:;?>.<,~`'
        [julius@station julius]$ ls
        !@#$%^&*()_+=-|\}]{[:;?>.<,~`  '  "  a and b
        [julius@station julius]$

这些是四个名字比较奇怪的文件。

Warning

以上示例只为说明使用。这里的许多字符是我们还没有讨论过的Shell元字符。在文件名中应该尽量避免使用标点符号,随意使用元字符可能产生意想不到的问题。

不要忽视这个警告。一般来说,文件名包括字母、数字和 ._-+~(A-Z、a-z、0-9、点、下划线、破折号、加号和波浪号)等标点符号。通常文件名由字母数字或点开头(见下文“隐藏文件”)。虽然有时你会见到文件名含有空格,但我们不鼓励这种做法。

以下两个示例显示滥用有特定意义字符的后果。在这里有两个Shell元字符(空格和大于号)被错误使用。

示例一:空格

        [hogan@station hogan]$ mkdir bad dir ①
        [hogan@station hogan]$ touch this and that ②
        [hogan@station hogan]$ mv this and that bad dir ③
        [hogan@station hogan]$ ls ④
        dir

①用户hogan本来想建立一个名为“bad dir”的目录,结果建立了两个分别名为bad和dir的目录。

②然后,用户hogan又试图使用touch命令建立名为“this and that”的文件,结果是他建立了三个名称分别为this、and和that的文件。

③现在用户hogan又以为他可以将文件“this and that”移动到叫做“bad dir”的目录里,但结果是他把四个文件this、and、that和bad(三个一般文件和一个目录)移动到目录dir中。

④因为以前的命令都“成功”执行了,直到现在用户hogan才发现他的错误。

当然用户hogan如果按备注中所说,在文件名外使用引号的话,就不会有以上问题。这点值得注意,因为你会遇到有空格的文件名。另外,文件名是允许以空格开头或结尾的,但这些在文件列表中“很难”识别出来。

示例二:误导

        [hogan@station hogan]$ mkdir bad->dir ①
        [hogan@station hogan]$ touch this ②
        [hogan@station hogan]$ mv this bad->dir ③
        [hogan@station hogan]$ ls ④
        bad-  dir

①用户hogan决定避免使用空格。这回他想建立名为bad->dir的目录,但结果建立了一个名为bad-的目录和一个名为dir的文件。(为什么?)

②接着,用户hogan使用touch命令建立名为this的文件,这步没有问题。

③现在用户hogan试图将文件this移动到目录bad->dir中,但结果是他把文件this移动到目录bad-里,并将命令输出(输出为空)重定向到了文件dir中。

④直到这时用户hogan才发现他的错误。

和前面相同,如果用户hogan使用引号就不会出现这样的问题。引号可以帮你解决很多问题,但你不能因此就随便建立不恰当的文件名。如果你的文件有“正常”的名字,我们以后要讲到的许多操作就会简单很多。

2.隐藏文件

以点(.)开头的文件和目录(记住,目录也是一种文件)是“隐藏”文件。只有在ls命令后附加特殊命令选项-a(all),或将开头的点(.)作为文件名的一部分,这些文件才会出现在文件列表中。这种“眼不见为净”的做法为文件列表减去许多凌乱项目。

在后面我们会学习如何使用“文件名匹配(globbing)”的方式一次命名多个文件。一般来说,除非特别列出开头的点(.),隐藏文件不会出现在“匹配”中。

除了隐藏文件外,开头的点没有其他意义。隐藏文件和目录可以和其他文件同样使用。

        [alice@station alice]$ mkdir .secret
        [alice@station alice]$ touch sample
        [alice@station alice]$ ls
        sample
        [alice@station alice]$ ls -a
        .  ..  sample  .secret
        [alice@station alice]$ mv sample .secret
        [alice@station alice]$ ls
        [alice@station alice]$ ls .secret
        sample
        [alice@station alice]$ cd .secret
        [alice@station .secret]$ ls
        sample
        [alice@station .secret]$

3.匹配(Globbing)

我们经常会对一个以上的文件上执行同一个命令。命令如cp -r和rm -r在整个目录分枝执行。Linux有更灵活的方法识别一组文件。bash命令Shell将一些特殊元字符作为“通配符(wildcard)”处理。bash Shell读取命令行时会执行一个进程叫做“元字符扩展”或“通配符扩展”,产生一个所有符合“通配符扩展”模式的文件名列表,然后将产生的列表传给命令去执行。这就是“文件名匹配(filename globbing)”。

*和?的使用比较简单。表2-3中通配符的用法有点复杂,但它是强大而有效的工具。

表2-3 通配符

括号通配符表示一组单个字符。所以[aeiou]匹配任何一个元音。一串相连的字符可以用破折号表示,如 [a-z] 表示小写字母。以^号开头的是被排除的选择,[^aeiou]代表元音以外的任何字母。“真正”的破折号或^号可用在斜线(\)后“表示”(以后我们还会详细说明)。即[a\-z]只匹配字符a、z和-。字符串和单个字符可以一起用。[A-Za-z0-9._\-+~] 匹配图2-14包括的所有“安全”文件名字符。

图2-14 “安全”文件名字符

假设当前工作目录包括以下文件:

        image1.jpg   image10.jpeg  page1.html   page3.htm   script1.pl
        image2.jpg   image11.jpeg  page2.html   page40.htm

表2-4说明这些通配符的用法。

表2-4 通配符

通配符可以在所有含有文件名的命令中使用,如命令:

        [bob@station bob] mv *.htm public_html

和以下命令相同:

        [bob@station bob] mv page3.htm page40.htm public_html

假设用户Bob的主目录包括表2-4中的文件。

技术备注:在没有给出一个或多个文件作为命令的一部分时,许多命令的行为和给出文件时是不一样的。在这样的情况下,如果使用通配符但是没有找到匹配的文件,会怎么样呢?在这种特殊情况下,bash Shell命令找不到匹配的文件,它会将原来的表达法作为命令的一部分,如下例所示:

        [bob@station bob]$ rm
        rm: too few arguments
        Try 'rm --help' for more information.
        [bob@station bob]$ rm z*
        rm: cannot lstat 'z*': No such file or directory

首先,rm命令没有找到任何文件,它给出错误信息。第二次,Shell通过模式z*找不到匹配的文件,结果z*本身被送到命令rm作为文件名。因为用户Bob没有名为z*的文件,命令不能执行,最终系统给出错误信息。

2.5.2 示例

1.寻找配置文件

用户alice最近浏览过DNS(域名服务——Domain Name Service)配置文件,但不记得它的文件名。她只记得这个文件以.conf结尾。为了缩小搜索范围,她使用文件名匹配列出目录/etc中所有以 .conf结尾的文件。

        [alice@station images]$ ls /etc/*.conf
        /etc/aep.conf       /etc/lftp.conf          /etc/pnm2ppa.conf
        /etc/aeplog.conf    /etc/libuser.conf       /etc/pwdb.conf
        /etc/cdrecord.conf /etc/logrotate.conf      /etc/resolv.conf
        /etc/esd.conf       /etc/lpd.conf           /etc/rndc.conf
        /etc/fam.conf       /etc/ltrace.conf        /etc/scrollkeeper.conf
        /etc/gpm-root.conf /etc/modprobe.conf       /etc/sysctl.conf
        /etc/grub.conf      /etc/mtools.conf        /etc/syslog.conf
        /etc/host.conf      /etc/named.conf         /etc/updatedb.conf
        /etc/initlog.conf   /etc/nscd.conf          /etc/updfstab.conf
        /etc/jwhois.conf    /etc/nsswitch.conf      /etc/warnquota.conf
        /etc/krb5.conf      /etc/ntp.conf           /etc/webalizer.conf
        /etc/krb.conf       /etc/pam_smb.conf       /etc/wvdial.conf
        /etc/ldap.conf      /etc/pbm2ppa.conf       /etc/xinetd.conf
        /etc/ld.so.conf     /etc/pine.conf          /etc/yp.conf

查看后,她记起来配置文件的文件名为resolv.conf。

2.静态库列表

用户Bob学习了程序使用的静态和动态连接库之间的区别。他知道静态连接库的名字都是libsomething.a,something是库的名字。他还知道库一般位于目录/usr/lib下。

当他查看系统中安装的静态库时,他在目录/usr/lib中找到近千个文件。为了缩小查看范围,他试着列出所有以a结尾的文件。

        [bob@station bob]$ ls /usr/lib/*a
        /usr/lib/liba2ps.a              /usr/lib/libimlib-ps.a
        /usr/lib/libacl.a               /usr/lib/libimlib-tiff.a
        /usr/lib/libanl.a               /usr/lib/libimlib-xpm.a
        ...
        /usr/lib/mozilla:
        plugins
        /usr/lib/samba:
        vfs

这里我们已经略去了列表中的很多部分,但我们还是可以看到问题所在。用户Bob的“匹配”不够详细,将一些以a结尾的目录也包括进去了。让我们看他如何改进,得到希望的结果。

        [bob@station bob]$ ls /usr/lib/lib*.a
        /usr/lib/liba2ps.a             /usr/lib/libimlib-ps.a
        /usr/lib/libacl.a              /usr/lib/libimlib-tiff.a
        /usr/lib/libanl.a              /usr/lib/libimlib-xpm.a
        ...
        /usr/lib/libimlib-jpeg.a        /usr/lib/libz.a
        /usr/lib/libimlib-png.a         /usr/lib/libzvt.a
        /usr/lib/libimlib-ppm.a

用户Bob觉得最常用的库应该会有描述性不强、但非常简短的名字。他列出所有名字只有1、2和3个字母的库。

        [bob@station bob]$ ls /usr/lib/lib?.a
        /usr/lib/libc.a  /usr/lib/libl.a  /usr/lib/libz.a
        /usr/lib/libg.a  /usr/lib/libm.a
        [bob@station bob]$ ls /usr/lib/lib??.a
        /usr/lib/libdl.a  /usr/lib/libgd.a  /usr/lib/librt.a
        /usr/lib/libfl.a  /usr/lib/libmp.a
        [bob@station bob]$ ls /usr/lib/lib???.a
        /usr/lib/libacl.a  /usr/lib/libgdk.a  /usr/lib/libosp.a  /usr/lib/librle.a
        /usr/lib/libanl.a  /usr/lib/libgif.a  /usr/lib/libpam.a  /usr/lib/librpm.a
        /usr/lib/libapm.a  /usr/lib/libgmp.a  /usr/lib/libpbm.a  /usr/lib/libSDL.a
        /usr/lib/libbfd.a  /usr/lib/libgpm.a  /usr/lib/libpci.a  /usr/lib/libssl.a
        /usr/lib/libbsd.a  /usr/lib/libgtk.a  /usr/lib/libpgm.a  /usr/lib/libttf.a
        /usr/lib/libefs.a  /usr/lib/libIDL.a  /usr/lib/libpng.a  /usr/lib/libusb.a
        /usr/lib/libesd.a  /usr/lib/libnsl.a  /usr/lib/libpnm.a  /usr/lib/libxml.a
        /usr/lib/libgal.a  /usr/lib/libogg.a  /usr/lib/libppm.a  /usr/lib/libzvt.a

用户Bob能否只用一个表达式就列出名字为1、2或3个字符的库?

3.列出Man Page

用户alice知道包含帮助手册页(man page)的文件位于目录 /usr/share/man下与帮助手册页章节相关的子目录中。

        [alice@station man]$ ls /usr/share/man/
        bg             hu            man2x   man8            ru
        cs             id            man3    man8x           ru.KOI8-R
        da             it            man3p   man9            ru.UTF-8
        de             it.ISO8859-1 man3x    man9x           sk
        el             it.UTF-8      man4    mann            sl
        en             ja            man4x   nl              sr
        es             ko            man5    pl              sv
        fi             man0p         man5x   pl.ISO8859-2    tr
        fr             man1          man6    pl.UTF-8        zh_CN
        fr.ISO8859-1   man1p         man6x   pt              zh_TW
        fr.UTF-8     man1x        man7   pt_BR
        hr          man2         man7x  ro

作为系统的一般用户,她只对第1、5、7章感兴趣。她使用文件名匹配表达式列出这些目录的内容。

        [alice@station man]$ ls /usr/share/man/man[157]
        /usr/share/man/man1:
        :.1.gz                      pbmtolj.1.gz
        [.1.gz                      pbmtoln03.1.gz
        411toppm.1.gz               pbmtolps.1.gz
        a2p.1.gz                    pbmtomacp.1.gz
        ...
        groff.7.gz                  wireless.7.gz
        groff_char.7.gz             x25.7.gz
        groff_diff.7.gz

如果用户alice对以上章节里,除了名为“n”章的所有man page都感兴趣,她可以使用文件名匹配范围表达式。

        [alice@station man]$ ls /usr/share/man/man[1-9]
        /usr/share/man/man1:
        :.1.gz                      pbmtolj.1.gz
        [.1.gz                      pbmtoln03.1.gz
        411toppm.1.gz               pbmtolps.1.gz
        a2p.1.gz                    pbmtomacp.1.gz
        ...
        named-checkconf.8.gz        zic.8.gz
        named-checkzone.8.gz
        /usr/share/man/man9:

2.5.3 练习题

Note

以下问题以问号(?)结尾,这个问号不是命令的一部分。

使用以下命令的输出回答下面5个问题。

        [elvis@station files]$ ls
        ebbs   eras   lakes  lit    loop   olden  rank   renew  robe   run    whirr
        echo   erect  lamed  lives  lorry  one    rapid  reply  robed  wagon  whorl
        elope  ergo   lash   loads  lost   ounce  rasp   retry  rock   wares  wile
        enact  erupt  lead   loath  loves  oust   rays   rho    rocky  ways   windy
        end    evens  leaks  lobby  lows   ovary  razor  rigid  rooms  weak   witty
        enjoy  evoke  leaps  locus  loyal  overt  read   rigs   roses  weep   wools
        entry  ewes   learn  logic  lucks  racks  reaps  rime   rouge  wench  wound
        envoy  lace   leech  login  oaks   radon  recta  riots  rove   west   wrens
        epic   laced  lick   loin   obese  raged  recur  risks  row    wet   writ

(1)命令ls r*s的输出应该包含以下哪个文件?( )

A.eras

B.raged

C.rigs

D.retry

E.racks

F.wrens

(2)命令ls r?? 的输出应该包含以下哪个文件?( )

A.eras

B.row

C.riots

D.rho

E.wet

F.run

(3)命令ls [aeiou]??? 的输出应该包含以下哪个文件?( )

A.ebbs

B.lead

C.oft

D.whip

E.oaks

F.oust

(4)命令ls *[^aeiou] 的输出应该包含以下哪个文件?( )

A.ebbs

B.rove

C.one

D.rasp

E.ways

F.era

(5)命令ls [aeiou]?e* 的输出应该包含以下哪个文件?( )

A.ebbs

B.rove

C.one

D.rasp

E.ways

F.rouge

使用目录/etc/X11/gdm的递归列表回答下列问题。

    [student@station student]$ ls -R /etc/X11/gdm/
    /etc/X11/gdm/:
    factory-gdm.conf  gnomerc  locale.alias  PreSession  XKeepsCrashing
    gdm.conf         Init    PostSession   Sessions
    /etc/X11/gdm/Init:
    Default
    /etc/X11/gdm/PostSession:
    Default
    /etc/X11/gdm/PreSession:
    Default
    /etc/X11/gdm/Sessions:
        default  Default  Failsafe  GNOME  KDE

(6)命令ls /etc/X11/gdm/S*/*a* 的输出应该包含以下哪个文件?( )

A./etc/X11/gdm/Init/Default

B./etc/X11/gdm/locale.alias

C./etc/X11/gdm/factory-gdm.conf

D./etc/X11/gdm/Sessions/Default

E./etc/X11/gdm/Sessions/Failsafe

F./etc/X11/gdm/Sessions/default

(7)命令ls /etc/X11/gdm/*/*[Ef] 的输出应该包含以下哪个文件?( )

A./etc/X11/gdm/gdm.conf

B./etc/X11/gdm/factory-gdm.conf

C./etc/X11/gdm/Init/Default

D./etc/X11/gdm/Sessions/GNOME

E./etc/X11/gdm/Sessions/KDE

F./etc/X11/gdm/Sessions/Failsafe

(8)命令ls /etc/*.?? 的输出可能包含以下哪个文件?( )

A./etc/issue.net

B./etc/mail.rc

C./etc/php.ini

D./etc/huh.??

E./etc/xpdfrc.ja

F./etc/gss-1.0

(9)命令ls /etc/[akp]??[0-9]* 的输出可能包含以下哪个文件?( )

A./etc/krb5.conf

B./etc/as5-0

C./etc/pbm2ppa.conf

D./etc/a2ps.cfg

E./etc/php.ini

F./etc/krc8

(10)命令ls /etc/[aeiou][^aeiou]??[aeiou]* 的输出应该包含以下哪个文件?( )

A./etc/adjtime

B./etc/issue

C./etc/aeplog.conf

D./etc/at.deny

E./etc/at.allow

F./etc/auto.tab

2.6 检查文件

主要概念

➢ file命令显示文件类型。

➢ cat命令显示文件内容。

➢ more命令和less命令逐页浏览文件。

➢ head命令和tail命令显示文件开始几行和最后几行。

➢ 在X图形环境里,可用nautilus检查文本文件。

2.6.1 讲义

查看文件

Linux系统有多种命令检查文件及其内容。这里我们来学习这些工具中最常用的几种。

file命令

任何文件的内容都是ASCⅡ(文本、HTML、Shell脚本、程序源码等)或二进制码(编译好的执行文件、压缩归档文件、声音文件等)格式。

本节讨论的命令只适用于ASCⅡ文件,如果在二进制文件上使用可能导致大小不一的问题(小至在显示屏上出现乱码,大到锁定终端显示)。这是因为二进制码文件可能包含任意二进制码,这其中的一些如果作为ASCⅡ文本解读,可能有特殊意义。所以在使用以下这些工具之前,最好用file命令检测任何你不认识的文件的类型。

        file [OPTIONS] [FILE...]

判断FILE的文件类型,将结果以标准输出显示。

使用在ASCⅡ文件上的范例:

        [nero@station nero]$ file index.html novel.ps mailer
        index.html:        HTML document text
        novel.ps:          PostScript document text conforming at level 3.0
        mailer:           perl script text executable

使用在二进制文件上的范例:

        [nero@station nero]$ file logo.jpeg symphony.mp3 archive.tgz
        logo.png:          PNG image data, 387 x 69, 8-bit grayscale, non-interlaced
        symphony.mp3:      MP3, 128 bits, 44.1 kHz, JStereo
        archive.tgz:       gzip compressed data, deflated, last modified: Thu Mar 20
    21:27:272003, os: Unix

cat命令

我们在本章的第三节讨论过这个命令,这里我们来介绍它的几个选项。

        cat [OPTIONS] [FILE...]

以标准输出连续显示FILE。

表2-5 cat命令选项

cat命令显示文件时会同时显示所有内容。大型文件在显示屏上一晃而过,难以阅读,所以cat命令比较适合内容小于一屏的文件。

more和less分页程序

more和less都可以在显示屏上浏览文本文件。它们的用法相似,比较新的less命令还有其他功能,如正确响应[PgUp]键、[PgDn]键和方向键的控制。

对less命令要特别熟悉,因为其他工具(如man)使用它提供分页功能。

        more [OPTIONS] [FILE...]

使用键盘控制,逐页显示FILE的标准输出。

表2-6 more命令选项

        less [OPTIONS] [FILE...]

使用键盘控制,逐页显示FILE的标准输出。

表2-7 less命令选项

表2-8 less(more)导航命令

less分页程序使用UNIX的一个标准概念——管道(pipe)。在以后的章节里我们会详细讨论管道,这里我们就less这一方便实用的功能对它进行简单介绍。管道和重定向相似,它们都将命令的输出重定向到非终端的地点。如果使用重定向(使用>),输出被重定向到指定的文件。管道将一个命令的输出作为另一个命令的输入。bash Shell命令使用字符|(在键盘上位于回车键上方)构建管道。

如果命令产生大量输出,可将这些输出作为命令less的输入,这样我们可以像浏览文件一样浏览这些输出,上下翻页和搜索。浏览结束后,退出less,输出就会消失。

用户Elvis使用ps aux命令浏览所有在机器上运行的进程。他知道这一输出会很大所以他选择使用管道将输出导入less浏览器。

        [elvis@station elvis]$ ps aux
        USER      PID %CPU %MEM   VSZ   RSS TTY  STAT START  TIME  COMMAND
        root        1  0.0  0.0  1392   92  ?    S    17:27  0:04  init [
        root        2  0.0  0.0    0    0   ?    SW   17:27  0:00  [keventd]
        root        3  0.0  0.0    0    0   ?    SW   17:27  0:00  [kapmd]
        root        4  0.0  0.0    0    0   ?    SWN  17:27  0:00  [ksoftirqd_CPU0]
        root        9  0.0  0.0    0    0   ?    SW   17:27  0:00  [bdflush]
        ...
        [elvis@station elvis]$ ps aux | less

现在他可以用浏览文件(或man page)的方式浏览ps命令的输出:使用空格键前进一页;b后退;/textEnter搜索文本text,q退出。

head命令

有时我们只需浏览文件最前面的几行。head命令提供这个功能。

        head [OPTIONS] [FILE...]

以标准输出形式显示FILE文件开始的10行。

表2-9 head命令选项

在下面的例子里,用户elivs先浏览文件/etc/group的开始10行,再浏览这个文件的开始5行。

        [elvis@station elvis]$ head /etc/group
        root:x:0:root
        bin:x:1:root,bin,daemon
        daemon:x:2:root,bin,daemon
        sys:x:3:root,bin,adm
        adm:x:4:root,adm,daemon
        tty:x:5:
        disk:x:6:root
        lp:x:7:daemon,lp
        mem:x:8:
        kmem:x:9:
        [elvis@station elvis]$ head -n 5 /etc/group
        root:x:0:root
        bin:x:1:root,bin,daemon
        daemon:x:2:root,bin,daemon
        sys:x:3:root,bin,adm
        adm:x:4:root,adm,daemon

如果将一个或多个文件名作为参数,head命令分别显示每个文件的开始几行,文件内容间使用文件名作为抬头将文件分开。下面用户elvis列出目录/etc/rc.d/init.d中所有红帽服务脚本的开始几行。

        [elvis@station elvis]$ head -5 /etc/rc.d/init.d/*
        ==> /etc/rc.d/init.d/acpid <==
        #!/bin/bash
        #
        #      /etc/rc.d/init.d/acpid
        #
        # Starts the acpi daemon
        ==> /etc/rc.d/init.d/anacron <==
        #!/bin/sh
        # Startup script for anacron
        #
        # chkconfig: 2345 95 05
        # description: Run cron jobs that were left out due to downtime
        ==> /etc/rc.d/init.d/apmd <==
        #!/bin/sh
        #
        # chkconfig: 2345 26 74
        # description: apmd is used for monitoring battery status and logging it via \
        #      syslog(8). It can also be used for shutting down the machine when \
        ==> /etc/rc.d/init.d/atd <==
        #!/bin/bash
        #
        #      /etc/rc.d/init.d/atd
        #
        # Starts the at daemon
        ==> /etc/rc.d/init.d/auditd <==
        #!/bin/bash
        #
        # auditd       This starts and stops auditd
        #
        # chkconfig: 2345 11 88
        ==> /etc/rc.d/init.d/autofs <==
        #!/bin/bash
        #
        # $Id: rc.autofs.in,v 1.632006/03/30 02:09:51 raven Exp $
        #
        # rc file for automount using a Sun-style "master map".
        ==> /etc/rc.d/init.d/avahi-daemon <==
        #! /bin/sh
        #
        # avahi-daemon:      Starts the Avahi Daemon
        #
        # chkconfig: 345 98 02
        ...

和less调页程序用法一样,可以使用head命令有选择地浏览命令的大量输出。

      [student@station student]$ ps aux | head -5
      USER      PID %CPU %MEM   VSZ   RSS TTY    STAT START   TIME  COMMAND
      root        1  0.0  0.1  2500   416 ?      S    10:51   0:03  init [5]
      root        2  0.0  0.0    0    0   ?      SW   10:51   0:00  [keventd]
      root        3  0.0  0.0    0    0 ?       SW   10:51   0:00 [kapmd]
      root        4  0.0  0.0    0    0 ?       SWN  10:51   0:00 [ksoftirqd/0]
      [student@station student]$

tail命令

      tail [OPTIONS] [FILE...]

与head命令对应,tail命令以标准输出形式显示FILE文件的最后10行。

表2-10 tail命令选项

下面的例子中,用户elivs先浏览文件/etc/group的最后10行,然后浏览它的最后5行。

        [elvis@station elvis]$ tail /etc/group
        named:x:25:
        gdm:x:42:
        postgres:x:26:
        apache:x:48:
        postdrop:x:90:
        postfix:x:89:
        squid:x:23:
        webalizer:x:67:
        ldap:x:55:
        elvis:x:500:
        [elvis@station elvis]$ tail -n 5 /etc/group
        postfix:x:89:
        squid:x:23:
        webalizer:x:67:
        ldap:x:55:
        elvis:x:500:

tail命令还有另一个极有用的选项:-f(follow)。和这个选项一起使用,tail命令先显示文件最后几行,然后处于“等待”状态,当文件添加新行时,显示这些新行。一般可用这个功能实时监控系统日志文件。一旦使用这一选项,命令提示不会返回。tail–f命令启动后会一直保持活动状态,不断显示新行,直到按Ctrl+C组合键中断进程。

2.6.2 示例

1.使用file识别文件

当使用cups命令显示系统配置时,prince在目录/usr/share/cups/banners中见到以下文件:

        [prince@station banners]$ ls /usr/share/cups/banners/
        classified  confidential  secret  standard  topsecret  unclassified

不清楚这些文件的类型,他使用file命令识别这些文件。

        [prince@station banners]$ cd /usr/share/cups/banners/
        [prince@station banners]$ file *
        classified:     PostScript document text conforming at level 3.0
        confidential:   PostScript document text conforming at level 3.0
        mls:            PostScript document text conforming at level 3.0
        secret:         PostScript document text conforming at level 3.0
        selinux:        PostScript document text conforming at level 3.0
        standard:       PostScript document text conforming at level 3.0
        te:             PostScript document text conforming at level 3.0
        topsecret:      PostScript document text conforming at level 3.0
        unclassified:   PostScript document text conforming at level 3.0

正如命令file显示的那样,这些是PostScript文件,它们是被送到打印机里作为横幅的。

2.使用file判断正确文件类型

用户elivs从他朋友的相册网站下载了一些图片,存储在名为pics的目录中。

        [elvis@station images]$ ls pics/
        dscn0936.png  dscn0942.png  dscn0953.jpg
        dscn0938.png  dscn0952.png  dscn0959.jpg

从文件后缀他发现其中4个文件是PNG格式,另两个是JPEG格式。他觉得有些奇怪,就使用file命令确认文件类型。

        [elvis@station images]$ file pics/*
        pics/dscn0936.png: PNG image data, 360 x 480, 8-bit/color RGB, non-interlaced
        pics/dscn0938.png: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced
        pics/dscn0942.png: PNG image data, 360 x 480, 8-bit/color RGB, non-interlaced
        pics/dscn0952.png: PNG image data, 360 x 480, 8-bit/color RGB, non-interlaced
        pics/dscn0953.jpg: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced
        pics/dscn0959.jpg: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced

原来那两个文件也是PNG格式,在文件命名时使用了错误的文件后缀名。

3.使用head快速浏览文件

用户blondie最近了解到,目录/etc/profile.d中所有以.sh结尾的文件都会在她每次登录时的bash Shell命令配置中使用。对这些文件的内容好奇,她使用以下一个命令浏览这些文件的头几行。

        [blondie@station blondie]$ head /etc/profile.d/*.sh
        ==> /etc/profile.d/colorls.sh <==
        # color-ls initialization
        alias ll='ls -l' 2>/dev/null
        alias l.='ls -d .*' 2>/dev/null
        COLORS=/etc/DIR_COLORS
        [ -e "/etc/DIR_COLORS.$TERM" ] && COLORS="/etc/DIR_COLORS.$TERM"
        [ -e "$HOME/.dircolors" ] && COLORS="$HOME/.dircolors"
        [ -e "$HOME/.dircolors.$TERM" ] && COLORS="$HOME/.dircolors.$TERM"
        [ -e "$HOME/.dir_colors" ] && COLORS="$HOME/.dir_colors"
        ==> /etc/profile.d/cvs.sh <==
        # change default from rsh to ssh for cvs command
        export CVS_RSH=${CVS_RSH-ssh}
        ==> /etc/profile.d/glib2.sh <==
        ## This caused GLib2 applications to convert filenames from
        ## locale encoding to UTF-8. If the locale encoding is already
        ## UTF-8 then it makes no difference.
        export G_BROKEN_FILENAMES=1
        ==> /etc/profile.d/gnome-ssh-askpass.sh <==
        SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
        export SSH_ASKPASS
        ==> /etc/profile.d/kde.sh <==
        # When/if using prelinking, avoids (some) use of kdeinit
        if [ -f /etc/sysconfig/prelink ] ; then
          source /etc/sysconfig/prelink
          if [ "$PRELINKING" = yes ] ; then
              [ -z "$KDE_IS_PRELINKED" ] && KDE_IS_PRELINKED=1 && export KDE_IS_PRELINKED
          fi
        fi
        # IPV6 support
        [ -z "$KDE_NO_IPV6" ] && KDE_NO_IPV6=1
        ==> /etc/profile.d/krb5-devel.sh <==
        if ! echo ${PATH} | /bin/grep -q /usr/kerberos/bin ; then
              PATH=/usr/kerberos/bin:${PATH}
        fi
        if ! echo ${PATH} | /bin/grep -q /usr/kerberos/sbin ; then
              if [ '/usr/bin/id -u' = 0 ] ; then
                      PATH=/usr/kerberos/sbin:${PATH}
              fi
        fi
        ...

4.使用head将多个文件并成一个文件

用户madonna对PAM——Linux的可插拔认证模块(Pluggable Authentication Modules)——感兴趣。她在目录/usr/share/doc/pam-0.75/txts中发现许多readme文件。

        [madonna@station madonna]$ cd /usr/share/doc/pam-0.99.6.2/txts/
        [madonna@station txts]$ ls
        README.pam_access    README.pam_limits      README.pam_shells
        README.pam_chroot    README.pam_listfile    README.pam_stack
        README.pam_console   README.pam_localuser   README.pam_stress
        README.pam_cracklib README.pam_mail         README.pam_succeed_if
        README.pam_debug     README.pam_mkhomedir   README.pam_tally
        README.pam_deny      README.pam_motd        README.pam_tally2
        README.pam_echo      README.pam_namespace   README.pam_time
        README.pam_env       README.pam_nologin     README.pam_timestamp
        README.pam_exec      README.pam_permit      README.pam_umask
        README.pam_filter    README.pam_postgresok  README.pam_unix
        README.pam_ftp       README.pam_rhosts      README.pam_userdb
        README.pam_group     README.pam_rootok      README.pam_warn
        README.pam_issue     README.pam_rps         README.pam_wheel
        README.pam_keyinit   README.pam_securetty   README.pam_xauth
        README.pam_lastlog   README.pam_selinux

她不愿逐一查看这些文件,希望可以将这些文件并成一个文件以便浏览。她知道可以使用cat命令将输出重定向到一个文件,但是她不清楚每个文件的文件名。所以她决定使用head命令选择显示许多行。这样,她可以浏览文件内容,还可以同时阅读分隔抬头行显示的文件名。

        [madonna@station txts]$ head -99999 README* > /tmp/pam_READMEs.txt
        [madonna@station txts]$ less /tmp/pam_READMEs.txt
        ==> README.pam_access <==
        pam_access ? PAM module for logdaemon style login access control
        ------------------------------------------------------------------------
        DESCRIPTION
        The pam_access PAM module is mainly for access management. It provides
        logdaemon style login access control based on login names, host or domain
        names, internet addresses or network numbers, or on terminal line names in case
        of non-networked logins.
        By default rules for access management are taken from config file /etc/security
        /access.conf if you don't specify another file.
        OPTIONS
        accessfile=/path/to/access.conf
        Indicate an alternative access.conf style configuration file to override
            the default. This can be useful when different services need different
            access lists.
        debug
        ...

5.使用tail监控多个文件

在红帽企业版Linux中,系统事件被记录在目录/var/log中的文本文件里,如/var/log/messages(记录一般系统事件)和/var/log/secure(记录有关敏感信息的事件)。随着事件的发生,新行会被实时添加到这些文件中。

如果系统管理员希望对这些日志文件和新添加的信息进行实时监控,他可以使用tail -f命令“跟踪”这些文件的最后几行。tail命令马上显示文件的最后10行和文件名。

        [root@station root]# cd /var/log
        [root@station log]# tail  -f messages secure
        ==> messages <==
        Jun 25 11:20:59 station kernel:  11: @cf13e4c0  length 800000de status 800100de
        Jun 25 11:20:59 station kernel:  12: @cf13e500  length 800000de status 000100de
        Jun 25 11:20:59 station kernel:  13: @cf13e540  length 80000042 status 00010042
        Jun 25 11:20:59 station kernel:  14: @cf13e580  length 800005ea status 000105ea
        Jun 25 11:20:59 station kernel:  15: @cf13e5c0  length 8000031e status 0001031e
        Jun 25 11:22:06 station su(pam_unix)[2229]: session closed for user madonna
        Jun 25 11:22:10 station su(pam_unix)[2352]: session opened for user root by
    elvis(uid=2291)
        Jun 25 11:23:06 station su(pam_unix)[2399]: session opened for user root by
    elvis(uid=2291)
        Jun 25 11:23:55 station su(pam_unix)[2399]: session closed for user root
        Jun 25 11:24:00 station su(pam_unix)[2441]: session opened for user elvis by
    elvis(uid=2291)
        ==> secure <==
        Jun 24 15:32:15 station sshd[11535]: Accepted publickey for root from 127.0.0.1
        port 36253 ssh2
        Jun 24 15:32:15 station sshd[11545]: Accepted publickey for root from 127.0.0.1
        port 36254 ssh2
        Jun 24 15:32:16 station sshd[11555]: Accepted publickey for root from 127.0.0.1
        port 36256 ssh2
        Jun 24 17:00:22 station sshd[819]: Received signal 15; terminating.
        Jun 24 17:29:05 localhost sshd[792]: Server listening on 0.0.0.0 port 22.
        Jun 24 17:30:49 localhost xinetd[803]: START: sgi_fam pid=1322 from=<no
    address>Jun 24 19:24:47 localhost xinetd[803]: START: sgi_fam pid=3175 from=<no
    address>Jun 25 08:43:54 localhost sshd[792]: Received signal 15; terminating.
        Jun 25 10:06:28 station sshd[834]: Server listening on 0.0.0.0 port 22.
        Jun 25 10:09:01 station xinetd[845]: START: sgi_fam pid=1134 from=<no address>

这时tail命令还在继续运行,但是输出会暂停,直到有新的系统事件发生并记录在这些文件里。tail命令又会马上显示新行和有关文件的文件名。

        ==> messages <==
        Jun 25 11:24:54 station su(pam_unix)[2481]: session opened for user root by
    elvis (uid=501)
        Jun 25 11:25:02 station su(pam_unix)[2481]: session closed for user root

系统管理员结束监控后,他使用Ctrl+C组合控制键结束命令。

2.6.3 练习题

使用file命令帮助完成以下两个问题。

(1)/usr/bin/htmlview是什么类型的文件?( )

A.编集好的ELF可执行文件

B.awk脚本

C.bash Shell脚本

D.符号连接

E./usr/bin/perl脚本

(2)/dev/log是什么类型的文件?( )

A.特殊字符文件

B.特殊块文件

C.套接字

D.命名的管道

E.编集好的ELF可执行文件

(3)如果文件b.txt不存在,以下哪个命令的行动和cp a.txt b.txt相同?( )

A.cat -5 a.txt b.txt

B.cat a.txt b.txt

C.cat -A a.txt > b.txt

D.cat a.txt > b.txt

E.以上都不是

(4)可以使用以下哪个组合键退出less调页程序?( )

A.q

B.x

C.Ctrl+C

D.A和C

E.以上都可以

(5)读取文件/etc/services时,调页程序less比more有优势是因为:( )

A.less允许用户逐页浏览输出,而more不可以

B.less可以使用一般方向键如:UpArrow和PgDown

C.less允许用户向后翻页,more只允许向前翻页

D.less允许用户使用简单的q退出,more要求使用组合键Ctrl+C

E.以上都可以

(6)以下哪个命令显示文件/etc/passwd开始的5行?( )

A.head -5 /etc/passwd

B.head -n /etc/passwd

C.head --five /etc/passwd

D.head /etc/passwd > 5

E.head /5 /etc/passwd

(7)为什么执行以下命令会有问题?( )

    [bob@station bob]$ head /bin/ls

A.用户bob没有权限读取文件/bin/ls

B.head命令必须和命令行选项-n一起使用,标明需要显示的行数

C.对于head命令来说,文件/bin/ls太小了

D./bin/ls是二进制码文件,而head命令主要用于文本文件

E.以上都不是

(8)用户如何终止tail -f命令?( )

A.不需要终止命令,命令在10秒钟之后自动终止

B.按q键

C.使用组合键Ctrl+Q

D.更换虚拟控制台

E.以上都不是

使用以下输出回答下面两个问题。

    [alice@station alice]$ cat -An /etc/fstab
            1  LABEL=/          /               ext3        defaults 1 1$
            2  LABEL=/boot      /boot           ext3        defaults 1 2$
            3  none             /dev/pts        devpts      gid=5,mode=620 0 0$
            4  none             /proc           proc        defaults 0 0$
            5  none             /dev/shm        tmpfs       defaults 0 0$
            6  /dev/hda2        swap            swap        defaults 0 0$

(9)以下哪个“不”正确?( )

A.文件/etc/fstab一共有6行

B./etc/fstab中的纵行由制表符,而不是空格分开

C./etc/fstab是文本,而不是二进制码文件

D.命令head -8 /etc/fstab和tail -6 /etc/fstab的结果完全一样

E.以上都不是

(10)命令cat /etc/fstab /etc/fstab和head /etc/fstab /etc/fstab的输出有何不同?( )

A.第一个命令只会显示文件/etc/fstab的内容一次

B.第一个文件将制表符作为可见字符显示

C.第二个命令只显示文件/etc/fstab副本开始的10行

D.第二个命令在输出中显示文件名作为标示

E.以上都不是

2.7 文件编辑

主要概念

➢ 文本编辑器不是文字处理器。

➢ Linux系统支持多种文本编辑器。

➢ nano是常用的一种命令行文本编辑器。

➢ gedit是常用的一种图形文本编辑器。

2.7.1 文本编辑器vs.文字处理器

Linux大量的配置选择是它高度灵活性的来源之一。配置信息一般存储在ASCⅡ纯文本文件中。系统管理会经常更新或更正这些配置文件。完成这些工作的工具是文本编辑器。

文本编辑器不是文字处理器。除了处理文字以外,文字处理器还允许用户改变字体、制表符设定、边框、文字对齐和其他影响文档打印形式的设定。文字处理器产生的文件内含指定这些设置的二进制码。文本编辑器只能用来修改纯ASCⅡ文件的文本内容,不内含任何二进制码。

如果要撰写信件、备忘录、布告、宣传单或其他可由编辑软件控制形式的文档,文字处理器是理想的选择。

文本编辑器适用来建立或修改配置文件、程序源代码、系统文档或任何(如HTML文档)呈现形式由阅读软件(如网页浏览器)控制的文档。本节主要讲述Linux系统管理,所以大部分的时候都会使用文本编辑器。

2.7.2 Linux文本编辑器

Linux内设整一套文本编辑器,含有的每个文本编辑器都有自己的优势和缺点。Linux同样包含文字处理器,例如OpenOffice套件里的Writer。

所有文本编辑器都适用于纯文本文件,所以你可以选择使用任何一个,不会出现兼容性问题。一般来说,对文本编辑器的选择基于编辑器的可用性、易用性、用户对编辑器的熟悉程度和其特殊功能。比如说,有些编辑器可以容易地产生格式正确的程序源代码,可以使编程容易、快速。本节中我们介绍了两个使用简单的文本编辑器:nano和gedit。vi是Linux中最受欢迎的文本编辑器,它也是功能最强大和最复杂的。因为它的复杂性,我们将不在这入门课程中介绍。

2.7.3 nano

nano是一个简单的,以面向显示的(全屏显示)文本编辑器。它在屏幕下方显示命令,并提供有关上下文的帮助。输入的字符会马上显示在文本中。

用法:

        nano [OPTIONS] [FILE]

将FILE以插入模式打开,进行编辑。

前面提过,在编辑过程中,nano命令会在屏幕下方出现,可以容易的调用编辑命令。主要的nano命令如表2-11所示。这里字母跟在^符号后表示Ctrl+字母的组合键,即^K是Ctrl+K。

表2-11 nano命令

表2-12 一些nano命令行选项

不恰当的换行可能损坏系统配置文件,所以在编辑这些文件时nano经常会和-w选项一起使用。

2.7.4 gedit

gedit是一个可以在X窗口环境使用的图形文本编辑器。可以从终端窗口的命令提示中输入gedit打开这个编辑器,或者从应用程序菜单中选择“附件”→“文本编辑器”。它打开一个大家都熟悉的、可以建立和编辑文本文件的文档窗口界面,这个界面还包括可以使用的工具栏图标,如查找和替换,剪切-复制-粘贴和打印。它标签式的窗口格式允许同时打开多个文件。它还有标准点击浏览界面可以浏览文件系统。

图2-15 gedit图形文本编辑器