第2章    Linux操作基础


2.1  Linux基本操作
  在使用Linux系统前,首先需要了解和掌握一些基本的操作,包括如何登录和退出系统、如何修改口令以及关闭和重启系统。

2.1.1  登录
  
Linux系统是一个多用户操作系统,系统的每个合法用户都拥有一个用户账号,包括用户名和口令等信息。任何用户在使用Linux系统前必须先登录系统。登录(login)过程就是系统对用户进行认证和授权的过程。登录时,用户须提供用户名和口令。如果输入有误则不能进入系统。
  每个Linux系统都有一个特殊的用户,称为超级用户。超级用户的用户名是root。root具有对系统的完全控制权限,非必要时应避免使用root登录。

  1. 终端与控制台
  
终端(terminal)是指用户用来与系统交互的设备,包括显示器、键盘和鼠标。每个用户都需要通过一个终端来使用系统。
  根据显示模式的不同,终端分为字符终端和图形终端。字符终端只能显示字符界面,接收键盘输入的命令;图形终端可以支持图形界面显示和鼠标操作。根据连接方式的不同,终端又可分为本地终端和远程终端。本地终端是直接与系统相连的终端,也称为控制台(console),是供系统本地用户使用的终端;远程终端指用户通过网络或其他通信方式远程地使用系统时所用的终端,可能是专门的终端机,更多的是PC机终端。

  通常一个系统只有一个物理控制台,但Linux系统用软件模拟的方式提供了多至12个虚拟控制台,包括6个字符终端和6个图形终端。虚拟控制台之间可以通过组合键Ctrl+Alt+Fn来切换,其中F1~F6对应6字符终端,F7~F12对应6个图形终端。系统默认启动6个字符控制台(对应的切换功能键为F1~F6)和1个图形控制台(对应的切换功能键为F7)。用户可以根据需要启动其他的控制台。

  2. 登录方式
  
Linux系统的登录方式可分为控制台登录和远程登录。
  1) 控制台登录
  系统启动后,会在每个启动了的控制台上显示登录界面。Linux允许同一用户在不同的控制台上以相同身份或不同身份多次登录,同时进行几项工作。各个控制台上的交互过程是相互独立的。例如,一个系统管理员拥有root账号和一个普通用户的账号。他可以在一个控制台上以普通用户身份登录进行一些日常工作,在另一个控制台上以root身份登录进行需要特权的系统管理工作。再如,程序员在一个控制台上调试程序,遇到程序因错误而不响应时,可以用同一身份从另一个控制台上登录,终止瘫痪的程序。

  在字符控制台上登录的方法是:将显示屏切换到一个字符控制台,就会看到系统登录提示符。在“login:”提示符后输入用户名,在“password:”提示符后输入口令。注意:Linux系统严格区分大小写,无论是用户名、口令、文件名等都是如此。登录成功后,系统显示Shell命令提示符,表示用户可以输入命令了。
  登录过程如下所示:
  login: cherry
  Password: (输入口令,不显示)
  Last login: Sat May 12 15:50:56 on :0
  You have mail.
  $ _

  注:本书约定,所有示例中,粗体为用户输入的内容,非粗体为系统的输出,括号“( )”内为说明信息。
  通常,系统启动后会默认地将显示屏切换到第7个控制台,并在其上启动一个图形登录界面。在图形控制台登录的方法是:在相应的输入框里输入用户名和口令并按回车键,系统验证通过后即进入图形桌面环境。

  2) 远程登录
  远程用户可以从远程终端登录到Linux系统上。远程登录的用户可以在自己所在的终端上像本地用户一样与系统交互,发布命令、运行程序并得到显示结果。允许远程登录标志着Linux是一个真正意义上的多用户操作系统。系统可以同时为多个远程的和本地的用户服务,对登录用户数也没有限制。
  从PC机上远程登录Linux系统的方法是:使用Windows的putty或其他虚拟终端软件,通过网络、拨号或串口方式与Linux系统建立通ssh信连接,连通后即可看到Linux系统的登录提示符“login”。

2.1.2  修改口令
  
用户在初次使用系统时,一般是用超级用户为其设置的初始口令登录。登录后应及时修改口令。此后,为安全起见,用户还应定期修改登录口令。口令应具有一定的长度和复杂度,使其不易被破解。口令还应便于记忆,若忘记口令只能找超级用户重新设置。
  在桌面环境下,可以在系统菜单中找到修改口令的界面(对于Fedora系统来说,它的位置是:『系统』→『首选项』→『个人』→『关于我』→『更改密码』)。在字符控制台界面修改口令应使用passwd命令。过程如下:

    $ passwd
     Change password for user cherry.
     (current) UNIX password: (输入原来的口令,无显示)
     New password: (输入新的口令,无显示)
     Retype new password: (重复输入新的口令,无显示)
     passwd: all authentication tokens updated successfully.
    $ _

2.1.3  退出
  
退出(logout)就是终止用户与系统的当前交互过程。操作完成后及时退出系统是一个良好的习惯,即使是暂时离开也应如此。
  在桌面上可以找到退出系统的按钮或菜单项。在字符控制台界面,用exit命令或在命令提示符后按Ctrl+d键即可退出系统。(注意:可能需要多次使用exit命令或Ctrl+d键直至退出系统。)
  退出后,系统回到登录界面,用户可以重新登录系统。

2.1.4  系统的关闭与重启
  
当系统需要关机时,必须使用关机命令来关闭系统,不能直接关闭电源。另外,当修改了系统的某一配置,或者安装了新的软件,有时需要重新启动系统使修改生效。在多用户系统中,关闭和重启系统会影响到所有已登录的用户,因而执行此操作需要有root权限。不过,为方便个人应用,Linux系统默认设置为允许登录图形桌面的普通用户关闭和重启系统。
  在桌面环境下关机或重启很简单,只要点击相应的按钮即可。此外,在控制台上按Ctrl+Alt+Del键也可以重启系统。

  在字符命令界面要使用命令关闭或重启系统。常用的关机命令是:
  # shutdown now
  常用的重启命令是:
  # reboot
  在关机命令的执行过程中,系统屏幕上会显示出关机操作的输出信息。要等到关机过程完成后方可切断电源。


2.2  Linux命 令
  Linux系统为用户提供了一套完备的命令,使用这些命令可以有效地完成各种工作。Linux的命令由Shell程序解释执行,所以也常称其为Shell命令。在使用Linux命令前首先要启动Shell程序。
  启动Shell的方式有多种,通常的方式是:
  ● 在字符终端登录,登录成功后Shell将自动启动;

  ● 登录到图形桌面上,在菜单中可以找到一个“终端”工具(对于Fedora系统的桌面,它的位置是:『应用程序』→『系统工具』→『终端』)。“终端”是一个软件仿真的虚拟终端,用于提供一个在图形环境下运行的字符命令行界面。打开“终端”窗口,Shell也随之启动。
  Shell启动完成后,显示命令提示符,提示用户可以输入命令了。对于普通用户,系统的默认提示符是“$”;对于root用户,系统的默认提示符是“#”。

2.2.1  命令的格式
  
一条Shell命令是由一到多个项组成的命令行,命令各项之间用空格分隔。命令的一般格式如下:
  命令名 [选项1] [选项2]…[参数1] [参数2]…
  其中,命令名是命令的名称,表示要执行的操作,通常为小写。选项是对命令的特别定义,指出怎么执行这个操作,一般以“-”开始。参数则是要操作的对象或操作数据。方括号括起的部分表明该项是可选的。例如:命令行rm -i abc中,rm是命令名,表示删除文件操作;-i是命令选项,表示删除前要提示用户确认;abc是命令参数,表示要删除的文件的名称。另外,当一个命令带多个选项时,可以只用一个“-”连起来,如rm -i -v abc可以写成rm -iv abc。

2.2.2  命令的输入与修改
  
Shell命令是通过终端键盘输入的。输入命令时可以使用一些编辑键来修改输入错误,控制命令的执行。表2-1所示是常用的Shell命令行编辑键。

  Shell的命令有时会很长,熟练地使用按键可以大大减化命令的输入。例如,当要输入的命令名或文件名较长时,只要输入前几个字符,再按一下Tab键,系统便会在可能的命令或文件名中找到相匹配的项,自动补齐其余部分。利用上下箭头键“↑”和“↓”可以翻找出前面曾经执行过的命令,避免重复的命令输入。

2.2.3  命令的执行
  
命令输入完成后,就可按Enter键提交给Shell运行。运行结果通常显示在屏幕上。运行完毕后,Shell重新显示命令提示符,准备接收下一条命令。
  在命令的执行过程中,如果输出的信息太多太快,可以按Ctrl+s键暂停滚屏。之后按下任意键即恢复滚屏。用户还可以按Ctrl+c键终止命令的运行。表2-2所示为常用的Shell命令运行控制键。

2.2.4  命令的分类
  
按照实现方式的不同,Shell命令分为内部命令和外部命令两种。内部命令全部由Shell程序自身提供,外部命令由一个个单独的程序实现。内部命令通常对应的是比较简单、使用频繁的功能,而外部命令则往往完成比较复杂或耗时的功能。
  按照命令的功能分类,Shell命令可以大致分为以下几类:
  ● 文件、目录操作;
  ● 文本编辑与处理;
  ● 备份与压缩;

  ● 系统监控与管理;
  ● 网络通信;
  ● 其他。
  其中,文件、目录操作和文本编辑是每一个Linux用户都要掌握的基本操作。本章将重点介绍常用的文件和目录操作命令,在第3章中介绍文本编辑器的使用,其余命令将在后续章节中陆续介绍。

2.2.5  简单命令
  
以下介绍几个简单而又常用的命令。
  who命令
  【功能】显示已登录的用户。
  【格式】who [选项] [am i]
  【选项】
  -H  显示各列的标题。
  -q  显示登录的用户名和用户数。
  【参数】带有参数am i时,显示自己的登录信息。
  【说明】显示内容分为4列:用户名、登录的终端名、登录时间和备注。有-q选项时,只输出用户名和用户数。

  例2.1  who命令用法示例:
  $ who
    root  tty1  May 25  11:39
    zhao  tty2  May 25  09:12
    cherry    :0  May 25  08:45
    cherry    pts/0  May 25  08:45  (:0.0)
  $ who -q
    root  zhao  cherry  cherry
    # users=4
  $ who am i
    cherry  pts/0  May 25  08:45  (:0.0)
  $

  echo命令
  【功能】显示命令行中的参数字符串。
  【格式】echo [选项] [字符串]…
  【选项】
  -n  输出字符串后光标不换行。
  【说明】如果字符串中含有空格符,用引号将字符串括起来,echo将按原样输出这个字符串,否则空格将被看做是多个字符串间的分隔符,echo依次输出这些字符串,中间用一个空格隔开。

  例2.2  echo命令用法示例:
  $ echo Hello!
    Hello!
  $ echo -n Hello!
    Hello! $ echo
  $ echo Hello   world!
    Hello world!
  $ echo “Hello   world!”
    Hello   world!
  $

  第2个echo命令输出字符串后没有换行,使后面的Shell提示符显示在它的输出后面了。第3个echo命令没有参数,它显示了一个空行。第4个echo命令带了2个字符串参数,尽管这两个字符串中间有多个空格分隔,但它们只被看做是参数分隔符而不是字符串的组成部分。echo依次输出了这两个字符串,中间用一个空格分隔。第5个echo命令带了1个字符串参数,它原样输出了这个字符串。
  date命令
  【功能】显示、设置系统日期和时间。
  【格式】date [选项] [+格式]

  【选项】
  -s  设置时间和日期。
  -u  使用格林威治时间。
  【参数】格式是由格式控制字符和其他字符构成的字符串,用于控制输出的格式。当格式字符串中有空格时,要用引号‘’或“”将格式字符串括起来。常用的格式控制字符如下:
  %r  用hh:mm:ss AM/PM(时:分:秒 上午/下午)的形式显示12小时制时间。
  %T  用hh:mm:ss(时:分:秒)的形式显示24小时制时间。
  %a  显示星期的缩写,如Sun。

  %A  显示星期的全称,如Sunday。
  %b  显示月份的缩写,如Jan。
  %B  显示月份的全称,如January。
  %m  用2位数字显示月份,如02。
  %d  用2位数字显示日期,如27。
  %D  用mm/dd/yy(月/日/年)的形式显示日期,如02/27/08。
  %y  用2位数显示年份,如08。
  %Y  用4位数显示年份,如2008。

  【说明】不带选项和格式参数时显示当前日期与本地当前时间。显示格式是:
  星期  月  日  时间  时区  年
  例2.3  date命令用法示例:
  $ date
    Mon  May  26  20:04:34  CST  2008
  $ date ‘+Today is %D, now is %r’
    Today is 05/26/08, now is 08:14:36 PM
  $ date ‘+%B %d, %Y’
    May 26, 2008
  $
  第1个date命令使用了缺省的显示格式。第2个date命令用了指定的显示格式。

  cal命令
  【功能】显示月份和日历。
  【格式】cal [[月份] 年份]
  【参数】月份是1~12的数字,年份是1~9999的数字。
  【说明】若带有一个参数,则该参数被解释为年份;若带有两个参数,则第1个参数表示月份,第2个参数表示年份。不带参数时,显示当年当月的日历。
  例2.4  cal命令用法示例:
  $ cal  #显示当年当月的日历
     July 2008
  Su  Mo  Tu  We  Th  Fr  Sa
      1  2  3   4    5

  6  7  8  9  10  11  12
  13  14  15  16  17  18  19
  20  21  22  23  24  25  26
  27  28  29  30  31
  $ cal 2 2008  #显示2008年2月的日历
      February 2008
  Su  Mo  Tu  We  Th  Fr  Sa
   1 2
  3  4  5   6    7    8    9
  10  11  12  13  14  15  16
  17  18  19  20  21  22  23
  24  25  26  27  28  29
  $

2.2.6  联机帮助
  
Linux命令多达数千个,其中常用的和比较常用的命令也有几百个,每个命令还有许多选项。不过,用户通常只需掌握几十个常用命令及其常用选项,其他的命令及详细用法可以在必要的时候通过命令的联机帮助查看。获得联机帮助的方式有以下几种。

  1. --help选项
  
许多Linux命令都提供了一个--help选项,执行带有--help选项的命令将显示该命令的帮助信息。例如:date --help将显示date命令的帮助信息。

  2.  man命令
  Linux系统配有一个联机手册,每条Linux命令都对应有相关的手册页。手册页是对命令的最详细、最权威的解释,因此是学习和使用Linux命令的必不可少的工具。
  每个命令的手册页主要包括以下几部分内容:
  NAME  命令的名称和功能。
  SYNOPSIS  命令的语法格式,所有可用的选项及参数。
  DESCRIPTION  命令的详细用法及每个选项的功能。
  OPTIONS  对命令的每个选项的详细说明。
  查看联机手册页的命令是man(manual)命令。

  man命令
  【功能】显示联机手册页。
  【格式】man命令名
  【说明】在浏览手册页时,用以下按键翻页、查找和退出:
  PageUp、b  向上翻一页。
  PageDown、Space  向下翻一页。
  ↑  向上滚一行。
  ↓、Enter  向下滚一行。
  /string     在手册页中查找字符串string。
  n     查找下一个字符串。
  q     退出。

  3.  info命令
  
除了联机手册外,Linux系统还提供了大多数命令的超文本形式的联机文档,可用info命令浏览。info命令与man命令的用法类似,但浏览起来更方便。


2.3  Linux文件操作
  文件系统是Linux系统的基本组成部分。Linux系统运行所依赖的各种程序和数据都以文件形式存储在磁盘上的文件系统中。
  文件系统统一存储和管理所有的文件,用文件名来标识各个文件。用户通过文件名来访问和使用文件系统中的文件。文件系统中的所有文件通过目录的形式组织和存放。目录是一种特殊的文件,其内容是该目录下的一组文件(包括子目录)的信息。目录将所有的文件分层分枝地组织在一起,形成文件系统的树型结构。

  用户使用Linux系统的最基本的操作就是对文件和目录的操作。与Windows系统相同,Linux系统提供了在图形窗口界面操作文件的便利手段。不过,在Linux系统中,最基本和最有效的操作文件的方法是使用命令。因此,用户应该熟练掌握用命令方式操作文件的方法。

2.3.1  Linux系统的文件
  1. 文件的命名
  
Linux文件名的最大长度是255个字符,通常由字母、数字、“.”、“_”和“-”字符组成。以“.”开头的文件名是隐含文件(在通常的文件列表时不显示)。例如:myfile、readme.txt、list_12、backup07-12-04都是常规的文件名,而.profile就是一个隐含文件的文件名。
  文件名中不能含有斜杠字符“/”和空字符“\0”,因为它们对Linux内核具有特殊含义,如“/”表示根目录或路径分隔符。文件名中也不应含有空格符、制表符、控制符以及以下字符,因为它们对Shell具有特殊含义:

  ;  |  <  >  `  “  ‘  $  !  %  &  *  ?  \  (  )  [  ]
  与Windows系统的文件名不同,Linux的文件名是区分大小写的,即字母相同,大小写不同的文件名被认为是不同的文件。例如:Readme与readme是不同的文件。

  2. 文件名通配符
  
1) 模式与通配符
  当一个命令需要对多个文件进行操作时,逐个写出每个文件名是件很麻烦的事。在这种情况下,使用模式可以简化对文件名的描述。
  模式的概念我们并不陌生,它是对一类事物的一种概括性描述。例如,在公布中奖号码时,通常用诸如“XXX558”形式的号码来代表所有后3位是558的号码,这就是一个数字模式,它代表了所有与之相匹配的号码。同样,当我们需要指定具有某种特征的多个文件名时,可以用一个表示文件名的字符串模式来描述。字符串模式由普通字符和一些具有特殊含义的字符组成,这些特殊字符称为通配符(wildcard)。通配符不代表某个具体的字符,而是代表多种选择,就像中奖号码模式中“X”的作用一样。这样,用一个模式来表示多个文件名,就不必在命令的参数中写出每个文件的名字了。

  2) 基本的通配符与匹配规则
  以下是在构造模式时常用的基本通配符:
  (1) 问号“?”:匹配任意的单个字符。如模式“abc??”匹配所有以abc开始,后面是2个任意字符的字符串。
  (2) 星号“*”:匹配0或多个任意字符(隐含文件的前缀“.”字符除外)。如模式“abc*”匹配所有以abc开始的字符串。模式“*abc”匹配所有以abc结尾的字符串,但不匹配“.abc”。
  (3) 方括号“[]”:匹配方括号中列出的字符集合中的任何单个字符。方括号与问号相似,只匹配单个字符。不同的是,问号与任何一个字符匹配,而方括号只与括号内字符集合中的一个相匹配。字符集合的描述方法有以下几种:

  ● 列举:逐个列出各个字符,如[abc]表示由a、b、c三个字符构成的字符集合。
  ● 范围:用“-”描述字符范围,如[a-z]表示由所有小写字母构成的集合。注意,范围内的字符按升序排列,因而[z-a]是无效的。可以指定多个范围,如[A-Za-z]表示所有英文字母。
  ● 排除:用“!”排除字符,如[!A-Z]表示除大写字母之外的所有字符构成的字符集合。例如,模式“abc[123]”匹配所有以abc开始,后面是1、2或3的字符串;模式“abc[0-9]”匹配所有以abc开始,后面是一个数字的字符串;模式“abc[!0-9]”匹配所有以abc开始,后面是一个非数字字符的字符串。

  例2.5  设现有的字符串是12个月份的英文单词,它们与以下模式匹配的结果是:
  模式“Ju??”     匹配以Ju开头,后接两个字符的字符
          串,即June和July。
  模式“???”         匹配长度为3的字符串,即May。
  模式“*ber”  匹配以ber结尾的字符串,即September、
          October、November和December。
  模式“?[ce]*”  匹配第2个字符是c或e的字符串,即
            February、September、October
         和December。

  1) 命令参数的模式置换
  当命令的参数中出现通配符时,Shell并不把该参数直接传递给命令,而是把它看做一个文件名模式字符串。Shell首先将现有的文件逐个与这个模式进行匹配比较,然后用所有匹配的文件名替换命令行中的模式字符串,最后再启动命令执行。因此,当命令执行时,它得到的实际参数是所有匹配的文件名的序列(可以是0~n多个文件名,中间用空格分隔)。
  以echo命令为例,它的功能是显示参数字符串。当其参数字符串中有通配符时,它显示的不是参数字符串本身,而是与该模式字符串相匹配的所有文件名,如例2.6所示。

  例2.6  设现有的文件是hoc、hoc.c、hoc.h、hoc.o、init.c、init.o、math.c、math.o、makefile,则命令echo *.c的输出结果如下:
  $ echo *.c  #实际运行echo hoc.c init.c math.c
  hoc.c init.c math.c
  $
  这个echo命令的输出不是参数字符串“*.c”,而是所有以.c结尾的文件名。这是因为当完成模式替换后,这个echo命令的实际运行参数是“hoc.c init.c math.c”。

  例2.7  设当前的目录下存放了一部书稿的所有文件。书稿分为12章,每章分为若干节,每节对应一个文件,文件的命名规则为“ch章号.节号”,如ch1.1,ch1.2,ch1.3,...,ch2.1,ch2.2,...,ch12.1,ch12.2,...,则以下echo命令执行的结果分别是:
  $ echo ch*  显示全书的所有文件名;
  $ echo ch3.*  显示第3章的所有文件名;
  $ echo ch?.*  显示1~9章的所有文件名;
  $ echo ch??.*  显示10~12章的所有文件名;
  $ echo ch[146-8]*  显示第1、4、6、7、8、10、11、12章的所有
           文件名;
  $ echo ch*.1  显示所有章的第1节的文件名。

  3. 文件的类型
  
常规意义上的文件是那些用于保存数据的文件,如由ASCII字符构成的文本文件、由应用程序产生的数据文件(电子表格、数据库表格、图片、视频等)以及由编译程序生成的可执行程序文件等。此外,Linux系统还定义了一些特殊类型的文件,它们在系统中具有特殊的用途。
  Linux系统支持以下文件类型(括号内是表示该类型的字符):
  ● 普通文件(-):普通意义上的文件,用于保存文本、数据或程序等信息。

  ● 目录文件(d):一种特殊文件,用于构成文件系统的树型结构。
  ● 设备文件(c、b):Linux系统将设备看做是一种特殊文件,设备文件分为字符设备文件(c)和块设备文件文件(b)两类。
  ● 符号链接文件(l):一种特殊文件,它的内容是到另一个文件的链接,用于实现文件的共享。
  ● 管道文件(p):一种特殊文件,用于在进程间传递数据。

  4. 文件的归属关系
  
Linux是一个多用户的系统,每个用户都要在系统中存放自己的文件。为了管理的需要,系统要能够区分文件的归属关系。Linux系统中的每个文件都有两个描述其归属关系的属性,这就是属主(owner)和属组(group owner)。
  文件的属主就是文件的所有者,通常是建立文件的用户,用其用户名标识。例如:用户zhao建立的文件的属主就是zhao。
  为便于管理,Linux系统将用户划分为用户组。文件的属组就是文件属主所在的用户组,用组名标识。例如:用户zhao所在的用户组是guest,则他所建立的文件的属组就是guest。

  5. 文件的访问权限
  
在多用户的系统,文件的保密和安全性至关重要。为防止文件被非法地使用或破坏,系统使用权限来限制用户对文件的访问。
  1) 文件的访问权限
  文件权限用于规定对于一个文件所能进行的操作。通常访问文件的操作分为读(显示浏览文件内容)、写(修改文件的内容)和执行(运行可执行文件)。相应的,Linux对文件定义了几种访问权限,见表2-3。

  当对一个文件执行一个未被授权的操作时,系统会拒绝执行,并显示 “Permission denied”的消息。

  2) 文件的权限范围
  在Linux系统中,一个文件可能会被多个用户使用。如果不加区分地对所有用户设置相同的文件访问权限,则难以满足不同用户对此文件的不同需求和权利。因此,Linux系统采用了更加细致的权限分配方式,即允许对不同类型的用户赋予不同的文件访问权限。
  Linux系统将每个文件的用户分为属主(user)、组用户(group)和其他人(other)3类,权限范围的划分及字符表示法如表2-4所示。在为文件设置访问权限时可以针对不同的权限范围分别设置。注意:root用户不受访问权限的限制。

  3) 文件类型与权限表示法
  文件的类型与权限是文件的重要属性,通常采用字符表示法表示,即用10个字符的字符串表示文件的类型和权限,规则如图2-1所示。其中,第1个字符表示文件的类型,取值是-、d、c、b、l和p,分别代表普通文件、目录、字符设备、块设备,符号链接和管道。后9个字符表示文件的访问权限,以3位为一组,分别表示u、g和o的读、写和执行权限。若某权限范围的用户有某权限,则对应的位上有该权限字符r、w或x,没有该权限则用“-”表示。

图2‑1  文件类型与访问权限的表示

  例如,某文件的类型和权限字符串是drwxr-x---,表明这是一个目录文件,它的属主对应的3位字符是rwx,表示属主有读、写和执行权限;组用户对应的3位字符是r-x,表示组用户对该目录有读和执行权限,没有写权限;其他人对应的3位字符是---,表示他们对该目录没有任何权限。又如,某文件的类型和权限字符串是-rwx--x--x,表明这是一个普通文件,它的属主有读、写和执行权限;组用户及其他人对该文件只有执行权限。
  文件的访问权限还有另一种表示方法,就是数字表示法。规则是:用数字1或0来表示权限字符,有相应权限的位为1,无权限的位为0,形成一个9位长的二进制数,用3位八进制数字来表示。例如:字符表示是rwxr-x---,数字表示就是750;字符表示是rwx--x--x,数字表示就是711。

  4) 文件权限的作用
  文件权限限制了对文件的访问操作。正确地设置文件权限可以允许正常的访问操作,同时阻止不期望的访问。表2-5显示了访问权限对普通文件和目录文件的限制作用。

  访问权限对普通文件的作用容易理解,需要注意的是权限对目录的限制作用。目录其实也是一个文件,只不过它的内容不是记录普通数据,而是其下的文件的列表数据。因此,显示目录中的文件列表就是对目录文件的读操作,改变目录下的文件列表(新建、删除、改名等)就是对目录文件的写操作,进入目录或其下级子目录就是对目录文件的执行操作。因此,对文件的删除权由其所在的目录的w权限决定(当然还要有x权),而不是文件本身的w权限决定的。在这一点上,Linux系统是不同于Windows系统的。

  另外,Linux系统规定非空目录不能删除。而空目录等同于文件,它的删除权取决于它的上一级目录的w权。
  下面的例2.8说明了目录的访问权限对删除文件的限制作用。
  例2.8  设有如下3个目录及其各自下属的3个文件,这些文件的删除权如下:
  目录1:drwxr-x--x
    文件1:-rwxr-xr-x    目录的属主可删除
  目录2:drwxrwxrwx
    文件2:-rwx------     任何人可删除
  目录3:dr-x------
    文件3:-rwxr-xr-x    只有目录属主可看到,任何人不可删

  目录1的权限为rwxr-xr-x,则目录的属主可以完全控制这个目录,其他人只能进入目录和显示文件列表,只有目录属主有权删除文件1。
  目录2的权限为rwxrwxrwx,即所有人可完全控制该目录。即使它下面的文件2的权限为rwx------,阻止了除属主之外的人访问这个文件,但他们却可以删除它。他们还有权在此目录中建立新文件、删除目录下的任意文件(包括空目录)和更改目录下的任意文件的文件名。所以在Linux中存放文件小心谨慎,不要把重要文件放在所有人可完全控制的目录里,即使这个文件的权限是0。

  目录3的权限为r-x------,则只有目录属主可以进入目录和看到目录中的文件列表,所有人(包括属主)都不能在目录中建立、删除文件或改文件名。即使它下面的文件3赋予其他人读和执行的权限,他们因为无法进入和使用这个目录,也就无法读和执行这个文件。这是用于保管重要文件的高安全度限制。

  6. 新建文件的默认权限
  
当新建一个文件或目录时,系统会为其设置最初的权限。文件的初始权限由文件创建掩码(creation mask)决定。掩码是一个9位二进制数字,通常用八进制数字表示,如022。掩码中的位与权限字符串相对应,掩码中为1的位限制对应的权限位的权限。例如:掩码022表示组用户和其他人没有w权限,对其他权限不做限制。
  文件创建时的默认权限有以下几种情况:

  1) 可执行文件
  通过编译程序生成的可执行文件,它的默认权限是777-掩码。例如:若掩码为022,则新文件的权限就是755。
  2) 非可执行文件
  对于非可执行文件(如文本文件、数据文件等),在创建时默认是没有x权限的,对这类文件的x权限需要显式地赋予,即通过chmod命令将其改为可执行文件。因此新建文件的权限是(777-掩码)& 666。这里的&是“按位与”运算,即先用777-掩码求出权限,再滤掉所有x位。例如:若掩码为022,则新文件的权限就是(777-022)& 666 = 644;若掩码为003,则新文件的权限就是(777-003)& 666 = 664。

  3) 目录
  同可执行文件一样,新建目录的默认权限是777-掩码。若掩码为022,则新目录的权限就是755。
  用户登录时,系统自动地为其设置了掩码,通常是022。用户可以用命令修改掩码,从而改变新建文件的默认权限,使之具有合适的安全性限制。

  7. 文件的其他属性
  
除了文件名、文件类型、归属关系和存取权限外,文件还有其他一些属性,包括:
  (1) 文件的时间标签,用于记录文件的时间属性,分为:
  ● 修改时间(modify time):文件内容被修改的最后时间。
  ● 访问时间(access time):文件最近一次被访问的时间。
  ● 变更时间(change time):文件属性变更的最近时间。
  (2) 文件的大小,即文件所占用的字节数。
  (3) 文件的链接数,即此文件硬链接的数目。

2.3.2  Linux系统的目录
  
计算机系统中存有大量的文件,为了有效地组织和管理这些文件,系统将文件分门别类地纳入目录中保存。目录好比是一个文件夹,用来容纳文件。目录中也可以包含子目录,形成层层嵌套的树型结构。
  在Linux系统中,目录是一种特殊的文件,其内容是目录中所包含的文件和子目录的列表。在访问一个文件时,需要先找到它所在的目录,再通过目录中记录的文件信息找到
文件。

  1. 目录结构
  
Linux的文件系统采用了树形目录结构,如图2-2所示。文件系统的根目录称为root目录。根目录下建有多个子目录,每个子目录下可以存放文件或下一级子目录,这样延伸下去,形成一个分层分枝的树形结构。root为树的“根”节点,目录是树中的“分枝”节点(图中用矩形表示),而文件则是树中的“叶子”节点(图中用椭圆表示)。
  系统安装完成后,文件系统的初始目录结构已经建立起来。用户也可以按需要创建自己的目录,实现有组织地、分层分类地存放文件。

图2‑2  Linux文件系统目录结构示意图

  2. 根目录与当前目录
  根目录是一个特殊目录,用“/”表示。它是整个文件系统的唯一的根,系统中的所有文件都在它及其下属的子目录中。
  用户在系统中工作时,始终处在某个目录之中,此目录称作当前目录。用户可以通过改变当前目录来变换其在文件系统中的位置。当前目录用“.”表示。当前目录的父目录用“..”表示。每个目录(包括空目录)中都至少有“..”和“.”这两个隐含文件。但根目录中的“..”和“.”都是指其自身。

  3. 路径
  
路径是文件在目录树中所处的位置。在对文件进行操作时,除需指明文件名外,还须指明该文件的路径。路径的表达方法是将若干个目录名连结起来,中间用斜杠“/”分开。
  根据起点的不同,路经分为绝对路经和相对路经两种。绝对路径是从根目录沿目录树到文件所在目录的路径。绝对路径都是以“/”开头的,并且是唯一的。例如:/home/zherry/project。相对路径是从当前目录沿目录树到文件所在目录的路径。例如:若当前目录的绝对路径是/home/cherry/project,则../book是一个相对路径,它的绝对路径是/home/cherry/book。在访问当前目录附近的文件时,使用相对路径可以简化路径的描述,尤其是当目录的层次较深的情况下。

  在Linux命令中,用“路径/”+“文件名”来唯一地指定一个文件。这里说的文件也包括目录文件。如:/home/cherry/ memo、/home/zhao、../cherry/project/hello等。当使用相对路径时,可以在路径前加“./”前缀,也可以省略。例如:若当前目录是cherry,则./book/doc1.c与book/doc1.c都是指当前目录下book子目录下的doc1.c文件;若当前目录是book,则./doc1.c与doc1.c也都是指当前目录下的doc1.c文件。

  4. 用户主目录
  
用户刚登录到系统中时所处的目录称为主目录(home directory),系统默认的用户主目录是/home/user-id。其中,user-id是用户的登录名。例如:用户cherry的主目录是/home/cherry(root例外,它的主目录是/root)。主目录就是用户登录后的初始工作目录,用“~”表示。用户对自己的主目录拥有全部权限,可以在其下任意组织自己的文件。

2.3.3  常用的目录操作命令
  
Linux系统提供了一些专门针对目录进行操作的命令,常用的是建立、删除、查看和改变目录,如表2-6所示。此外,由于目录也是文件,所以许多文件操作命令,如复制、移动、删除、更改属性等,也适用于对目录进行操作。这些命令在2.3.4小节介绍。

  1. 显示与改变当前目录
  
访问当前目录中的文件时是不需要加路径名的,因此,当需要集中对某个目录中的文件进行操作时,先进入这个目录,使其成为当前目录,就可大大简化命令的输入。要了解自己当前处在哪个目录下,可用pwd(present working directory)命令;要改变当前目录,可用cd(change directory)命令。
  pwd命令
  【功能】显示当前目录的绝对路径。
  【格式】pwd

  例2.9  pwd命令用法示例:
  $ pwd
  /home/cherry
  $
  cd命令
  【功能】改变当前目录为指定的目录。
  【格式】cd [目录]
  【说明】不指定目录参数时,进入用户的主目录。

  例2.10  cd命令用法示例:
  $ cd /usr/bin
  $ pwd
   /usr/bin
  $ cd
  $ pwd
   /home/cherry
  $ cd ./project/hello
  $ pwd
   /home/cherry/project/hello
  $ cd ../../book
  $ pwd
   /home/cherry/book
  $

  2. 显示目录内容
  
显示目录内容就是列出目录中所包含的文件以及文件的各种相关信息,子目录也作为一个文件列出,用于显示目录中的文件列表的命令是ls(list)命令。通常在进行文件操作前,应先用ls命令了解现有文件的状况。
  ls命令
  【功能】显示指定文件或指定目录中的所有文件的信息。
  【格式】ls [选项] [文件或目录] …
  【选项】
  -a   显示所有文件及目录, 包括隐藏文件、“.”及“..”目录。

  -R   递归显示下层子目录。
  -F      显示文件类型描述符(*为可执行的普通文件,
      /为目录文件,…)。
  -d      显示目录的信息而非其内容。
  -u      显示文件的最近访问时间,与-l连用。
  -c      显示文件的最近变更时间,与-l连用。
  -t      按文件修改时间排序显示。
  -l      按长格式显示文件详细信息。

  【说明】
  (1) 参数为普通文件时,显示指定的文件的信息;参数是目录时,显示指定目录下的文件列表信息(除非有-d选项);未指定文件或目录时,显示当前目录中的文件列表信息。
  (2) 不带选项时,按字母顺序列出目录中所有非隐藏文件的文件名。
  (3) 长格式显示时,每个文件的信息占一行,格式如下:
文件类型与权限 链接数 属主名 属组名 文件大小 最近修改时间 文件名

  例2.11  ls命令用法示例:
  $ cd ~
  $ ls  #显示当前目录下的文件名
  book   memo   project
  $ ls /home  #显示目录/home下的文件名
  cherry   mary    zhao
  $ ls -a  #显示当前目录下的所有文件名
  .   .bash_profile  .emacs   memo
  ..   .bashrc  .gtkrc   project
  .bash_logout   book  .kde
  $ ls -F  #显示当前目录下的文件名及类型
  book/   memo   project/
  $ ls -l  #显示当前目录下的文件的详细信息

  drwxrwxr-x  2  cherry  faculty  4096  Oct 14  12:50  book
  -rwxr-x---  1  cherry  faculty   522  Oct 12  14:21  memo
  drwxr-x---  2  cherry  faculty  4096  May 3  10:09  project
  $ ls -l memo  #显示文件memo的详细信息
  -rwxr-x---  1  cherry  faculty   522  Oct 12  14:21  memo
  $ ls book  #显示目录book下的文件名
  doc1   doc2
  $ ls -dl book  #显示目录book文件的信息
  drwxrwxr-x  2  cherry  faculty  4096  Oct 14  12:50  book
  $ ls memo book  #显示文件memo,目录book下的文件名
  memo
  book:
  doc1   doc2

  $ ls *  #等价于ls book memo project
  memo
  book:
  doc1   doc2
  project:
  hello    hoc
  $ ls -RF  #递归显示当前目录,显示各个文件名与类型
  .:
  book/   memo   project/
  ./book:
  doc1   doc2
  ./project:
  hello/     hoc/
  ./project/hello:
  hello*   hello.c   hello.o   makefile
  ./project/hoc:
  hoc*    hoc.c    hoc.h  init.c     math.c
  $

 

  注意:第10个ls命令使用了通配符“*”作为参数,在命令执行前先进行参数匹配置换,“*”被置换为当前目录下的所有文件名,因此,该命令的实际运行参数为book memo project。

  3. 创建与删除目录
  
为了分类保存文件,用户可以建立自己的目录。建立目录用mkdir(make directory)命令,删除目录用rmdir(remove directory)命令。
  mkdir命令
  【功能】建立目录。
  【格式】mkdir [选项] 目录…
  【选项】
  -m 权限  按指定的权限建立目录。
  -p  递归建立目录。即,若目录的父目录不存在,则一并建立其父目录。
  【说明】未指定目录权限时,默认权限为777-创建掩码。

  例2.12  mkdir命令用法示例:
  $ ls
  book    memo    project
  $ mkdir -m 744 temp  #建立temp目录,权限744
  $ ls
  book    memo    project    temp
  $ ls -ld temp
  drwxr--r--  2  cherry  faculty   4096  May 25 20:07  temp
  $ mkdir -p ./backup/version1  #递归建立./backup/version1目录
  $ ls . backup 
  .:
  backup   book    memo    project    temp
  backup:
  version1
  $

  第2个mkdir命令在当前目录下的backup目录下建立version1目录,此时,若backup目录已存在就直接建立version1目录,否则就先建立backup目录,然后再建立version1目录。最后的ls命令显示了当前目录的变化和backup目录的内容。
  rmdir命令
  【功能】删除目录。
  【格式】rmdir [选项] 目录…
  【选项】
  -p    递归删除目录,即当子目录删除后其父目录为空时,也一同被删除。
  【说明】若目录不空,则删除操作不能成功。

  例2.13  rmdir命令用法示例:
  $ ls
  backup   book   memo    project    temp
  $ rmdir temp  #删除空目录temp
  $ ls
  backup   book   memo    project
  $ rmdir project  #删除非空目录project
  rmdir: ‘project’: Directory not empty
  $ ls
  backup   book   memo    project
  $ rmdir -p ./backup/version1   #递归删除目录./backup/version1
  $ ls
  book    memo    project
  $

  第2个rmdir命令删除当前目录下的非空目录project,操作失败。第3个rmdir命令删除backup目录下的空目录version1,然后再删除变空的目录backup。

2.3.4  常用的文件操作命令
  
Linux系统提供了丰富的文件操作命令,可以完成各种各样的文件操作。而且,大部分文件操作命令也适用于目录文件。本小节介绍几个常用的文件操作命令,见表2-7。

  1. 文件的显示
  
阅读一个文本文件的最简单的方法就是用文件显示命令将文件内容显示在屏幕上。显示文本文件的常用命令是cat(concatenate)、more和less命令。
  cat命令
  【功能】显示文件内容。
  【格式】cat [选项] [文件]…
  【选项】
  -A    显示所有字符,包括换行符、制表符及其他非打印字符。
  -n    对输出的所有行进行编号并显示行号。
  -b    和-n相似,但对于空白行不编号。
  -s    将连续的空白行压缩为一个空白行。
  【说明】指定多个文件时,依次显示各个文件;未指定文件时,读标准输入(默认为键盘)并显示。

  例2.14  cat命令用法示例:
  $ cat doc1  #显示一个文件
   To see a world in a grain of sand,
   And a heaven in a wild flower,
   Hold infinity in the palm of your hand,
   And eternity in an hour.
  $ cat -n doc1  #显示一个文件,加行号
   1  To see a world in a grain of sand,
   2  And a heaven in a wild flower,
   3  Hold infinity in the palm of your hand,
   4  And eternity in an hour.

  $ cat  #显示标准输入内容
   This is the 1st line.
   This is the 1st line.
   This is the 2nd line.
   This is the 2nd line.
   This is the 3rd line.
   This is the 3rd line.
   <Ctrl+d>

  $ cat doc1 doc2  #显示多个文件
   To see a world in a grain of sand,
   And a heaven in a wild flower,
   Hold infinity in the palm of your hand,
   And eternity in an hour.
   A robin redbreast in a cage,
   Puts all heaven in a rage.
  $

  第3个cat命令后没带文件参数,所以在开始执行时,光标停留在下一行,等待键盘输入。用户每输入一行,cat就显示一行,直到按Ctrl+d键结束输入。第4个cat命令依次读取并显示了两个文件的内容。
  cat在显示输出时不会停下来,因此对长文件不好用。要浏览长文件的内容,可以使用more或less命令。它们可根据显示屏幕的大小形态将文件内容划分为一页页的显示,用户可以以交互方式控制翻页或卷行。

  more命令
  【功能】分屏显示文件内容。
  【格式】more [选项] [文件]…
  【选项】
  -p       不滚屏,清屏。
  -s       将连续的空白行压缩为一个空白行。
  +n      由第n行开始显示。
  +/str     由含有str字符串的地方开始显示。
  【说明】浏览时可使用如下键进行控制,浏览到末页后自动退出。未指定文件参数时,默认为读标准输入。
  Enter  向下翻一行。

  Space  向下翻页。
  b  向上翻页。
  /string  查找字符串string。
  n  查找下一个字符串。
  q  退出。
  例2.15  more一个长文件(见图2-3):
  在浏览过程中,屏幕左下角会显示“more”,命令因此得名。当浏览到末页时命令会自动退出。与more命令相比,less命令具有更好的交互性。用户可以完全控制浏览的过程,上下翻页和滚行,到末页时也不会自动退出。less的名字借用于英文短语“more or less”,在这里表示它是more命令的一个替代品。man命令就是采用less控制浏览手册页的。

图2‑3  用more命令显示文件

  less命令
  【功能】交互式浏览文件内容。
  【格式】less [选项] 文件…
  【选项】与more相似。
  【说明】浏览时可以用PageUp、PageDown上下翻页,用↑、↓上下滚行。其他按键与more相同。

  2. 文件的复制、移动与删除
  
复制文件用cp(copy)命令,删除文件用rm(remove)命令,移动文件和重命名文件用mv(move)命令。
  cp命令
  【功能】复制文件。
  【格式】cp [选项] 源文件 目标文件
  cp [选项] 源文件… 目标目录
  【选项】
  -i    交互模式,当目标文件存在时,提示是否覆盖。
     键入y或Y覆盖,键入其他字符不覆盖。
  -r    递归复制目录。

  -b    为被覆盖的文件建立备份。备份文件的名称是原文件名后加“~”。
  -f    强制复制。即如果目标文件存在且打不开,则先删除它,然后再复制。
  -p    保持文件原有属性。
  -v    显示操作结果。
  【说明】若只有两个参数,且参数2不是已存在的目录,则将参数1指定的文件复制到参数2指定的文件;若参数2是已存在的目录,则将参数1指定的文件复制到该目录下,文件名不变。若多于两个参数,且最后一个参数是已存在的目录,则将前面参数指定的文件复制到该目录下,文件名不变;若多于两个参数,且最后一个参数不是已存在的目录则报错。

  例2.16  复制一个文件:
  $ ls
   hello   hello.c   hello.o   makefile
  $ cp hello hello.save  #在当前目录下复制一个文件
  $ ls
   hello   hello.c   hello.o   hello.save   makefile
  $ cp -i hello.c hello.save  #交互式复制一个文件
   cp: overwrite ‘hello.save’?  y
  $ ls -F ..
   hello/  hoc/
  $ cp -v makefile ../hoc  #复制文件到一个已存在的目录下
   ‘makefile’ -> ‘../hoc/makefile’

  $ cp -v makefile ../hoc1  #复制文件到上一级目录下
    ‘makefile’ -> ‘../hoc1’
  $ ls .. ../hoc
   ..:
   hello  hoc   hoc1
   ../hoc:
   hoc  hoc.c  hoc.h  init.c  math.c    makefile
  $
  第2个cp命令将hello.c文件复制到已存在的hello.save文件,-i选项提示用户确认是否覆盖,输入y确认。第3个cp命令中,由于../hoc是已存在的目录,所以cp将makefile文件复制到../hoc目录下,名称不变。第4个cp命令中,../hoc1不存在,所以cp将makefile文件复制到../目录下,文件名为hoc1。

  例2.17  复制多个文件到一个目录下:
  $ ls
   hoc  hoc.h  init.c  math.c   makefile
   hoc.c  hoc.o  init.o  math.o
  $ mkdir temp
  $ cp *.o temp  #等价于cp hoc.o init.o math.o temp
  $ ls temp
   hoc.o  init.o  math.o
  $ cp *.h *.c ../src  #多个参数,且最后的参数不是已有目录
   cp: copy multiple files, but last argument ‘../src’ is not a directory
  $

  第1个cp命令将当前目录下3个.o文件复制到当前目录下的temp目录下,名称不变。第2个cp命令要将当前目录下所有.c和.h文件复制上级目录下的src目录下,但因src目录不存在,故操作失败。
  例2.18  复制整个目录:
  $ ls -R project
   project:
   hello   hoc
   project/hello:
   hello      hello.c    hello.o    makefile
   project/hoc:
   hoc      hoc.c    hoc.h    init.c    math.c    makefile

  $ cp -r project project.bak  #递归复制project目录
  $ ls-R project.bak
   project.bak:
   hello     hoc
   project.bak/hello:
   hello     hello.c   hello.o   makefile
   project.bak/hoc:
   hoc  hoc.c  hoc.h  init.c    math.c    makefile
  $
  当指定-r选项时,cp的参数是目录文件,此时cp执行的是目录的复制。本例中,cp命令将当前目录下的project目录完整地复制到project.bak目录,包括project下的两个子目录,以及子目录下的所有文件。

  rm命令
  【功能】删除文件。
  【格式】rm [选项] 文件…
  【选项】
  -f    忽略不存在的文件,不作提示。
  -i    删除前提示用户确认。
  -r    递归删除目录。
  -v    显示操作结果。
  【说明】若参数是目录文件,需要有-r选项,否则报错。

  例2.19  用rm命令删除文件:
  $ ls
   a.out   hello   hello.c   hello.o   makefile   temp
  $ rm a.out  #删除一个文件
  $ ls
   hello   hello.c   hello.o   makefile    temp
  $ rm -v hello    #删除一个文件,显示结果
   removed ‘hello’
  $ rm -i hello.*  #删除多个文件,逐个提示确认
   rm: remove regular file ‘hello.c’?  n
   rm: remove regular file ‘hello.o’?  y
  $ ls -F

   hello.c    makefile   temp/
  $ rm -r temp  #删除一个目录
  $ ls
   hello.c    makefile
  $
  注意:用rm命令删除的文件是永久删除,无法恢复。因此,要谨慎使用rm命令,尤其是用通配符时。例如:rm -r *.bak命令删除当前目录下所有带有“.bak”后缀的文件。若在“*”后面误敲了一个空格,变成rm -r * .bak,这将清除当前目录下的所有文件。所以,在使用带通配符的参数时,先用echo验证一下参数,以免因模式写错造成不期望的结果。

  mv命令
  【功能】移动文件、重命名文件。
  【格式】mv [选项] 源文件 目标文件
      mv [选项] 源文件… 目标目录
  【选项】
  -i    覆盖前提示用户确认。
  -f    不提示用户确认,直接覆盖。
  -b    为被覆盖的文件建立备份。备份文件的名称是原文件名后加“~”。
  -v    显示操作结果。

  【说明】若只有两个参数,且参数2不是已存在的目录,则将参数1指定的文件移动到参数2指定的文件;若参数2是已存在的目录,则将参数1指定的文件移动到该目录下,文件名不变。若多于两个参数,且最后一个参数是已存在的目录,则将前面参数指定的文件移动到该目录下,文件名不变;若多于两个参数,且最后一个参数不是已存在的目录则报错。

  例2.20  用mv命令重命名文件:
  $ ls
   hello    hello.c    hello.o    makefile  temp
  $ mv hello hello.save
  $ ls
   hello.c    hello.o  hello.save   makefile    temp
  $
  在原位置将一个文件移动为另一个文件,变化的只有文件名,因此这个mv命令实现了文件换名。

  例2.21  用mv命令移动文件:
  $ ls
   hello.c   hello.o   hello.save   makefile    temp
  $ mv -v hello.save hello.o temp
   ‘hello.save’ -> ‘temp/hello.save’
   ‘hello.o’ -> ‘temp/hello.o’
  $ ls
   hello.c  makefile  temp
  $ mv -v makefile temp/makefile.old
   ‘
makefile’ -> ‘temp/makefile.old’
  $ ls . temp
   .:
   hello.c  temp
   temp:
   hello.o       hello.save     makefile.old
  $

  第1个mv命令将当前目录下的hello.save和hello.o文件移动到temp目录下,文件名不变;在第2个mv命令中,由于参数temp/makefile.old不是已存在的目录,所以mv将makefile文件移动到了temp目录下,文件名为makefile.old。

  3. 文件内容的统计与排序
  
Linux提供了许多用于文件内容处理的命令,比较常用的有统计文件字数的wc(word count)命令和对文件内容排序的sort命令。
  wc命令
  【功能】显示文件的字节数、字数和行数。
  【格式】wc [选项] [文件]…
  【选项】
  -c     只统计字节数。
  -l       只统计行数。
  -m    只统计字符数。
  -w    只统计字数。

  说明】未指定选项时,显示行数、字数和字符数;未指定文件时,读标准输入文件。
  例2.22  统计一个文件的内容:
  $ cat poem
   To see a world in a grain of sand,
   And a heaven in a wild flower,
   Hold infinity in the palm of your hand,
   And eternity in an hour.
  $ wc poem
   4   29  131  poem
  $

  此例中wc命令的执行结果显示:poem文件有4行、29个字、131个字符。注意:每行后的换行符“\n”也被统计在字符数内。
  例2.23  统计标准输入的内容:
  $ wc
   This is the 1st line.
   This is the 2nd line.
   This is the 3rd line.
   <Ctrl+d>

    3     15    66
  $
  此例中,wc命令开始执行时,光标停留在下一行,等待键盘输入。用户输入3行后,按Ctrl+d键结束输入。wc随后显示结果:输入了3行、15个字、66个字符。

  sort命令
  sort命令是个常用的文字处理命令,它将文本文件的各行按ASCII字符顺序由小到大排序,并输出排序后的结果。
  【功能】对文本文件中的各行按字符顺序排序并显示。
  【格式】sort [选项] [文件]…
  【选项】
  -b  忽略开始的空白。
  -d  只考虑字母、数字和空格。
  -f  忽略大小写。
  -kn    指定从第n个字段开始的内容作为排序关键字。
  -r  逆序排列。
  【说明】未指定文件时,读标准输入文件。

  例2.24  排序一个文件的内容:
  $ cat emp_list
   Zhang Fei       430759701022003  1970/10/22
   Guan Yu      342869680413001  1968/04/13
   Liu Bei      210324650708001  1965/07/08
   Diao Chan   651302801225012  1980/12/25
   Xi Shi      120638780214006  1978/02/14
  $ sort emp_list  #按全行内容排序
   Diao Chan    651302801225012  1980/12/25
   Guan Yu      342869680413001  1968/04/13
   Liu Bei      210324650708001  1965/07/08
   Xi Shi      120638780214006  1978/02/14
   Zhang Fei    430759701022003  1970/10/22

  $ sort –k3 emp_list  #按第3个字段开始的内容排序
   Xi Shi      120638780214006  1978/02/14
   Liu Bei      210324650708001  1965/07/08
   Guan Yu      342869680413001  1968/04/13
   Zhang Fei    430759701022003  1970/10/22
   Diao Cha       651302801225012  1980/12/25
  $ sort –k4 -r emp_list  #按第4个字段开始的内容逆序排序
   Diao Cha       651302801225012  1980/12/25
   Xi Shi      120638780214006  1978/02/14
   Zhang Fe          430759701022003  1970/10/22
   Guan Yu      342869680413001  1968/04/13
   Liu Bei      210324650708001  1965/07/08
  $

  emp_list是一个员工列表,每行是一个员工的记录,包括4个字段:姓、名、身份证号和出生年月日。字段之间用空格分隔。第1个sort命令依次按第1、2、3、4字段的内容排序;第2个sort命令依次按第3、4字段的内容排序;第3个sort命令按第4字段的内容逆序排序。
  例2.25  排序标准输入的内容:
  $ sort
   Hello.
   This is a test.

   End.
   <Ctrl+d>
   End.
   Hello.
   This is a test.
  $

  不带参数时,sort命令从标准输入设备读输入内容直到按下Ctrl+d键,随后输出排过序的各行内容。

  4. 改变文件属性
  
用户可以用命令修改已有文件的访问权限等属性,达到控制文件的使用的目的。改变文件的访问权限用chmod(change mode)命令,改变文件的时间标签用touch命令。
  chmod命令
  【功能】修改文件或目录的存取权限。
  【格式】chmod [选项] [数字权限模式] 文件…
      chmod [选项] [字符权限模式表达式]… 文件…
  【选项】
  -R  递归地改变指定目录及其下的文件和子目录的
      权限属性。

  【说明】
  (1) 字符权限模式表达式的格式是:<权限范围><操作><权限字符>
   权限范围:  u 属主,g 组用户,o 其他用户,a 所有用户
   操作:  + 增加权限,- 取消权限,= 赋权限
   权限字符:  r 读,w 写,x 执行
  如:u=rw表示为文件属主赋予读/写权。
  (2) 多个表达式之间用逗号分隔,且不能有空格。如:u=rw,g-r。
  (3) 只有文件的属主和root有权限修改文件的权限。
  例2.26  用chmod命令修改文件的存取权限:
  $ ls -l testfile
   -rw-r--r--  1   zhao  guest   169  May 11 20:01  testfile
  $ chmod a+x testfile    #修改testfile的权限,为所有人增加执行权
  $ ls -l testfile
   -rwxr-xr-x 1  zhao  guest   169  May 11 20:01  testfile

  $ chmod o-x testfile   #修改testfile的权限,取消其他用户的执行权
  $ ls -l testfile
   -rwxr-xr--  1  zhao  guest   169  May 11 20:01  testfile
  $ chmod g=rx,o=x testfile   #设testfile权限为组用户可读和执
               行,其他人可执行,属主权限不变
  $ ls -l testfile
   -rwxr-x—x  1  zhao  guest   169  May 11 20:01  testfile
  $ chmod 664 test  file  #设testfile的权限为664
  $ ls -l testfile
   -rw-rw-r--   1  zhao  guest   169  May 11 20:01  testfile
  $ chmod go= test  file  #取消组用户和其他用户对testfile的任
               何权限
  $ ls -l testfile
   -rw-------  1  zhao  guest   169  May 11 20:01  testfile
  $

  注意:最后一个chmod命令的模式表达式中没有权限字符,表示组用户(g)和其他用户(o)没有任何权限,属主(u)的权限不变。
  touch命令
  【功能】修改文件的修改时间和访问时间的时间标签为现在时间。
  【格式】touch [选项] 文件…
  【选项】
  -a  仅改变文件的访问时间。
  -m  仅改变文件的修改时间。
  -c  文件不存在时,不创建文件。
  -t STAMP  使用STAMP指定的时间标签,而不是系统现在时间。

  【说明】若指定的文件不存在,就建立一个新的空文件(除非使用-c选项)。
  例2.27  用touch命令修改文件的时间戳:
  $ ls -l hello.c
   -rw-r--r--  1  zhao   guest    66  May 10 21:34  hello.c
  $ touch  hello.c  #“触动”一个已有文件
  $ date
   Wen  May  16  10:05:19  CST  2008
  $ ls -l hello.c  #显示文件的修改时间
   -rw-r--r--  1  zhao   guest    66  May 16 10:05  hello.c
  $ ls -lu hello.c  #显示文件的访问时间
   -rw-r--r--  1  zhao   guest    66  May 16 10:05  hello.c
  $ touch  abc  #“触动”一个新文件
  $ ls -l abc
   -rw-r--r--  1  zhao   guest     0  May 16 10:08  abc
  $

  第1个touch命令将hello.c文件的最近修改和访问时间改为现在时间, 这样做的目的通常是为了促使编译程序重新生成目标代码。第2个touch命令的参数abc不是一个已有的文件,结果是生成了一个空文件。touch的这个功能经常被用来快速地建立一个空文件。

  5. 设置文件掩码
  
用户可以用umask命令查看和设置文件创建掩码。
umask命令
  【功能】设置、显示文件创建时的权限掩码。
  【格式】umask [选项] [掩码]
  【选项】
  -S  以字符形式显示掩码对应的权限。
  【说明】若指定了掩码,则将该掩码作为新建文件的权限掩码。若未指定掩码,则显示现在的权限掩码。

  例2.28  umask命令的用法示例:
  $ umask  #显示当前掩码
   0022
  $ touch testfile1  #新建一个文本文件,权限644
  $ ls -l testfile1
   -rw-r --r--  1  zhao  guest   0    Oct 13  11:21  testfile1
  $ mkdir testdir  #新建一个目录,权限755
  $ ls -ld testdir
   drwxr-xr-x  2  zhao  guest   4096  Oct 13  11:25  testdir
  $ umask -S 007  #重新设置掩码为007,用字符方式显示
   u=rwx, g=rwx, o=

  $ touch testfile2  #新建一个文本文件,权限660
  $ ls -l testfile2
   -rw-rw----    1   zhao  guest   0  Oct 13  11:28  testfile2
  $ gcc -o hello hello.c  #编译一个c程序,生成可执行文件hello,权限770
  $ ls -l
   -rwxrwx---  1  zhao  guest    1668  Oct  13  11:34  hello
  $
  第1个不带参数的umask命令显示当前的掩码值;后面的操作显示了掩码对于新建的文件和目录的初始权限的作用。第2个umask命令将掩码设置为007,并用字符方式显示掩码作用后的默认权限。其后的操作显示了掩码对于新建立的文件的作用。

  6. 文件查找与搜索
  
如果用户不记得某个文件的具体位置了,可以根据一些条件(如文件名、类型、时间、属主等)在目录树中进行搜索。有时候,用户还需要对满足某些条件的所有文件统一进行某种处理。这些都需要文件查找功能。查找文件用find命令,它按照指定的条件来查找文件,并可对匹配的文件执行各种命令。find命令提供了很多查找条件,功能很强大,是一个非常优秀的查找工具。
  另外一个功能强大的工具是grep(global regular expression parser)命令,用于在文件中搜索字符串。grep命令支持用正则表达式描述的搜索模式,因而可以实现十分复杂、细致的搜索操作。

  find命令
  【功能】从指定的目录开始向下查找满足条件的文件,并对找到的文件执行指定的操作。
  【格式】find [目录]… [表达式] [操作]
  【表达式】表达式用于指定搜索的条件。可以指定多个条件,各条件表达式之间用逻辑运算符连接,缺省的运算符是与(-a)运算。
  -name 文件名    查找与指定的文件名相匹配的文件。可以使
            用通配符来构造文件名模式,带有通配符时
           要用‘’或“”将模式字符串括起来,如 ‘*.txt’。
  -user 用户名  查找指定用户所拥有的文件。
  -group 组名      查找指定的组所拥有的文件。
  -mtime [+-]n      查找在n天前修改过的文件。“+n”表示超过n天,
           “-n”表示不超过n天,“n”表示正好n天。
  -atime [+-]n      查找在n天前访问过的文件。
  -ctime [+-]n      查找在n天前变更过的文件。

  -mmin[+-]n   查找在n分钟前修改过的文件。“+n”表示超过n分钟,
        “-n”表示不超过n分钟,“n”表示正好n分钟。
  -amin [+-]n   查找在n分钟前访问过的文件。
  -cmin [+-]n   查找在n分钟前变更过的文件。
  -type x   查找类型为x的文件。x是表示文件类型的字符(f为普
        通文件、d为目录、b为块设备文件、c为字符设备文
        件)。
  -size [+-]n[bckM]  查找大小为n的文件,后面的字符表示单位。
           c为字节,b为块(512 B),k为千(1024 B)字节,
           M为兆(1024 KB)字节。缺省为b。“+n”表示
           超过n,“-n”表示不超过n,“n”表示正好n。
  -a、-and  与运算符。
  -o、-or  或运算符。
  !、-not  非运算符。

  \( 表达式\)      优先运算符。括在括号内的表达式优先计算。
  【操作】操作用于指定对搜索到的文件要进行的处理。
  -print  显示找到的文件名。
  -ls  显示文件的详细信息。
  -exec 命令 {} \;  对找到的文件执行指定的命令。
  -ok 命令 {} \;  与-exec相同,只是执行命令时提示用户确认。
  【说明】未指定搜索条件时,显示目录下的所有文件,包含隐藏文件。未指定目录时,默认为当前目录。未指定操作时,缺省的操作是-print。

  例2.29  按条件查找并显示结果:
  $ ls
   a.out    hello.c    hello.o    makefile    temp
  $ ls temp
   hello.save
  $ find . -name ‘hello*’ –print     #在当前目录下查找名字以                  hello开头的文件
   ./hello.c
   ./hello.o
   ./temp/hello.save
  $ find ! -name ‘hello*’      #查找名字不以hello开头的文件
   ./a.out
   ./makefile
   ./temp

  $ find . ! -name ‘hello*’ -type f  #查找名字不以hello开头的普
                  通文件
   ./a.out
   ./makefile
  $ find /var/spool/mail -size +0  #查找/var/spool/mail目录下所
                  有非空文件
   /var/spool/mail
   /var/spool/mail/cherry
   /var/spool/mail/root
  $ cd ~/project
  $ find . \( -name ‘*.c’ -o -name ‘*.h’ \) -atime -3  #查找扩展名为.c
或.o,并且在过去不到3日内被访问过的文件
   ./hello/hello.c
   ./hoc/hoc.c
   ./hoc/hoc.h
  $

  第1个find命令带有一个-name表达式,表示按名查找条件。目录是当前目录。操作是显示找到的文件。
  第2个find命令带有一个-name表达式和一个非运算符“!”,表示查找条件为不与该名字相匹配的文件;目录名未指定,默认为当前目录;操作未指定,执行默认的-print操作。
  第3个find命令带有-name和-type两个表达式,-name表达式前带有“!”运算符,两表达式之间没有运算符,缺省地表示“与”运算-a。
  注意:按逻辑运算的优先关系,“非”运算优先于“与”运算,因此查找条件是不与名字相匹配的,并且类型为普通文件的文件。

  最后的find命令带有两个-name和一个-atime表达式,前两个表达式之间是“或”运算关系,用括号括起来表示先进行“或”运算,再与第3个表达式进行“与”运算。因此,此命令查找条件是与第1个表达式或第2个表达式的名字相匹配的,并且满足访问时间限制的文件。如果没有括号,由于“或”运算的优先级低于“与”运算,所表达的查找条件是不同的。注意:表达式之间以及表达式与运算符之间必须有空格分隔。

  例2.30  查找并处理结果:
  $  ls *
   hello:
   hello   hello.c hello.o    makefile   temp
   hoc:
   hoc   hoc.c   hoc.h    hoc.o   init.c init.o   math.c  math.o    makefile
  $ find . -name ‘*.o’ -ok rm {} \;  #查找所有扩展名为.o的文件并提示是否删除
   < rm … ./hello/hello.o > ?  n
   < rm … ./hoc/hoc.o > ?  y
   < rm … ./hoc/init.o > ?  y
   < rm … ./hoc/math.o > ?  n
  $ ls *
   hello:
   hello    hello.c    hello.o    makefile    temp
   hoc:

   hoc    hoc.c    hoc.h    init.c    math.c    math.o    makefile
  $ cd hello
  $ find temp -size 0 -exec rm -v {} \; #删除temp目录下所有长度为0的文件
   removed  ‘temp/errlog’
  $ find ~ -type d -exec chmod 750 {} \; #将主目录下所有目录的权限改为750
  $ find ~ -type d -exec ls -ld {} \;  #显示主目录下所有目录文件的详细信息
   drwxr-x---  5  cherry  faculty  4096  Dec 9   10:09  .
   drwxr-x---  3  cherry  faculty  4096  Oct 14  12:50  .kde
   drwxr-x---  2  cherry  faculty  4096  Oct 14  12:50  .kde/Autostart
   drwxr-x---  2  cherry  faculty  4096  Oct 22  14:21  book
   drwxr-x---  6  cherry  faculty  4096  Oct 23  10:09  project
   …

  $ find /var/log -atime +5 -exec rm {} \;  #删除/var/log目录下5日前访问过的文件
  $ cd ..
  $ date ‘+%T’
   20:26:19
  $ find -name ‘*.c’ -exec touch {} \; #修改所有.c文件的时间为现在时间
  $ find -name ‘*.c’ -exec ls -l {} \;  #显示这些文件的时间
   -rw-rw-r--  1  cherry  faculty    96    May  17  20:26  ./hello/hello.c
   -rw-rw-r--  1  cherry  faculty   522    May  17  20:26  ./hoc/hoc.c
   -rw-rw-r--  1  cherry  faculty   196    May  17  20:26  ./hoc/init.c
   -rw-rw-r--  1  cherry  faculty   290    May  17  20:26  ./hoc/math.c
  $ find . -name ‘list[0-9][0-9]’ -type f -mtime 1 -exec wc -l {} \;  #查找昨天修改过的,名为list加两个数字的普通文件,统计行数

   15  ./hello/temp/list11
   18  ./hello/temp/list13
  $ find . -name ‘list[0-9][0-9]’ -type f -mtime 1 -exec cat {} \;  #显示这些文件的内容
   0631105  Zhang Li  68  79  C
   0631110  Li Ming  89  92  A
   …
   0631134  Ma Linlin  78  81  B
   0631307  Zhen Xiao  62  73  C
   0631315  Chen Jing  84  72  B
   …
   0631341  Wu Tianli  79  78  B
  $

  第1个find命令查找扩展名为.o的条件,用提示确认的方式(-ok)执行删除操作。用户输入“y”或“Y”即删除,输入其他字符则放弃删除。
  最后两个find命令带有同样的搜索条件,但前一个的操作是列出满足条件的两个文件的行数,后一个的操作是顺序显示两个文件的内容。
  grep命令
  【功能】在文本文件中查找与指定模式相匹配的字符串,显示含有匹配字符串的行。
  【格式】grep [选项] 模式 [文件]…

  【选项】
  -v  列出不包含匹配字符串的行。
  -c  不显示匹配的行,只列出匹配的行数。
  -l  只显示含有匹配字符串的文件名。
  -r  递归地搜索目录下的所有文件和子目录。
  -n  在每个匹配行前加行号显示。
  -i  匹配时不区分大小写。如模式“may”可匹配
      may、May和MAY。
  -w  匹配整个单词,而不是单词的一部分。如模式
      “magic”只匹配magic,而不匹配magical。

  【说明】
  (1) 未指定文件时,读标准输入文件。
  (2) 模式中可以使用如下特殊字符,带有特殊字符或空格符时,需将模式字符串用引号“”或‘’括起来:
  [ 、]指定匹配字符的范围。如模式“[Mm]ain”匹配Main和main。
  \<、\> 标注词首与词尾。如模式“\<man”匹配manic和man,但不
      匹配Batman;模式“man\>”匹配man和Batman,但不匹配
      manic。
  ^、$  标注行首与行尾。如“^The”匹配行首的The,而不匹配其
      他位置的The。
  \|   表示模式间的或关系。如“Saturday\|Sunday”匹配Saturday或
     Sunday。

  例2.31  在一个文件中搜索:
  $  cat poem
   To see a world in a grain of sand,
   And a heaven in a wild flower,
   Hold infinity in the palm of your hand,
   And eternity in an hour.
  $  grep and poem   #在poem文件中搜索“and”,显示匹配的行
   To see a world in a grain of sand,
   Hold infinity in the palm of your hand,
  $ grep -c and poem   #只显示含有“and”字符串的行数
        2
  $  grep -v and poem   #显示不含“and”字符串的行
   And a heaven in a wild flower,
   And eternity in an hour.

  $  grep -i and poem  #搜索“and”,忽略大小写
   To see a world in a grain of sand,
   And a heaven in a wild flower,
   Hold infinity in the palm of your hand,
   And eternity in an hour.
  $  grep -i ‘\<and’ poem   #搜索以“and”开头的字符串,忽略大小写
   And a heaven in a wild flower,
   And eternity in an hour.
  $  grep -n ‘in a’ poem  #显示含有“in a”的行,加上行号
   1: To see a world in a grain of sand,
   2: And a heaven in a wild flower,
   4: And eternity in an hour.

  $  grep -w ‘in a’ poem      #搜索与“in a”完全匹配的词(词组)
   To see a world in a grain of sand,
   And a heaven in a wild flower,
  $  grep ‘[sh]and’ poem    #搜索“sand”或“hand”
   To see a world in a grain of sand,
   Hold infinity in the palm of your hand,
  $  grep ‘sand\|hand’ poem    #搜索“sand”或“hand”
   To see a world in a grain of sand,
   Hold infinity in the palm of your hand,
  $ grep ‘^and’ poem         #搜索位于行首的“and”(未找到)
  $

  注意:当搜索的字符串模式中含有特殊字符时,需要用引号括起来,如最后一个grep命令的“^and”。若无特殊字符则可省略引号,如第1个grep命令中的“and”。
  例2.32  在多个文件和目录中搜索:
  $ grep printf hoc/*.c  #在hoc目录中所有扩展名为.c的文件中
               搜索“printf”
   project/hoc/hoc.c:  printf(“Usage: hoc expr;\n”);
   project/hoc/hoc.c:    { printf(“%s\n”, buf);
   project/hoc/ math.c:   fprintf(stderr, “Error: division by zero\n”);

  $  cd ~/
  $  grep -rl printf project  #在project目录树中搜索含有“printf”的
               文件
   project/hello/hello
   project/hello/hello.c
   project/hoc/hoc
   project/hoc/hoc.c
   project/hoc/math.c
  $


2.4  输入/输出重定向
2.4.1  命令的输入与输出
  
Shell命令或应用程序在执行时,往往需要从输入设备接收一些输入数据,并将处理结果输出到输出设备上。在Linux系统中,这些输入/输出设备都被作为文件对待。对应输入/输出设备的文件称为I/O文件。Linux系统定义了三个标准I/O文件,即标准输入文件stdin、标准输出文件stdout和标准错误输出文件stderr。在默认的情况下,stdin对应终端的键盘,stdout对应终端的屏幕,stderr也对应终端的屏幕。

  典型的命令和应用程序都设计为使用标准I/O设备进行输入和输出。它们从stdin接收输入数据(如C函数scanf和getchar等都是读stdin的函数),将正常的输出数据写入stdout(如C函数printf和putchar等都是写stdout的函数),将错误信息写入stderr(如C函数fprintf(stderr, …)是写stderr的函数)。在命令开始运行时,Shell会自动为它打开这3个标准I/O文件,并建立起文件与终端设备的连接。这样,当命令读stdin文件时,就是在读取键盘输入;当写stdout或stderr文件时,就是在往屏幕上输出。图2-4描述了这种默认的标准输入/输出数据的走向。

图2‑4  标准输入/输出示意图

  注意:标准I/O文件与实际设备之间的关联关系是在命令运行之际由Shell为其建立的,命令本身并不知道这种关联关系。在特别指明的情况下,Shell也可以重新定义标准I/O文件与实际设备或文件之间的关联关系,从而改变命令的输入/输出的实际走向。这就是输入/输出重定向。
  利用输入/输出重定向以及基于输入/输出重定向实现的管道机制,用户可以灵活地改变Linux命令的输入/输出走向,或将多个命令的输入/输出相衔接,实现灵活多变的功能。

2.4.2  输入重定向
  
输入重定向是指把命令的标准输入改变为指定的文件(包括设备文件),使命令从该文件中而不是从键盘中获取输入,如图2-5所示。输入重定向主要用于改变那些需要大量标准输入的命令的输入源。

图2‑5  标准输入重定向示意图

  输入重定向的格式为:命令 < 文件
  当提交这样的一个命令行时,Shell首先断开键盘与命令的stdin之间的关联,将指定的文件关联到stdin,然后运行命令。这样,该命令就会从这个文件中读取标准输入信息。
  例2.33  输入重定向的应用:
  $  cat afile
   This is the 1st line.
   This is the 2nd line.
   This is the 3rd line.
  $  cat < afile
   This is the 1st line.
   This is the 2nd line.
   This is the 3rd line.
  $

  本例中,两个cat命令的功能是等效的,但执行方式却不同。第1个cat带有一个文件参数afile,它运行时是在读取afile文件。而第2个cat没有带任何参数,因此它运行时是在读stdin文件,是Shell把它的stdin重定向到了afile文件上,将afile的内容作为标准输入送给了cat,对此cat本身并不察觉。
  同cat命令一样,许多Linux命令都设计为以参数的形式指定输入文件,若未指定文件就缺省地从标准输入读入数据。对于这样的命令,用参数指定文件与用输入重定向指定文件的效果是一样的(如上例中的两个cat命令),所以没有必要使用输入重定向。但对那些设计为只能从标准输入读取数据的命令(如mail、tr、sh等命令)来说,把要输入的数据事先存入一个文件中,再将命令的输入重定向到此文件,就能避免在命令运行时从终端上手工输入大量数据的麻烦。

2.4.3  输出重定向
  
输出重定向是指把命令的标准输出或标准错误输出重新定向到指定文件中。这样,该命令的输出就不显示在屏幕上,而是写入到文件中。
很多情况下都可以使用输出重定向功能。例如,如果某个命令的输出很多,在屏幕上不能完全显示,或者命令是在无人监视的情况下运行,那么将输出重定向到一个文件中,就可以方便从容地查看命令的输出信息。
  输出重定向的一般形式为:
  ● 标准输出重定向:  命令 > 文件
  ● 标准错误输出重定向:  命令 2> 文件
  ● 合并输出重定向:  命令 &> 文件
  ● 附加输出重定向:  命令 >> 文件

  1. 标准输出重定向
  
标准输出重定向就是将命令的标准输出保存到一个文件中,如图2-6所示。
  标准输出重定向格式为:命令 > 文件
  当提交这样的一个命令行时,Shell首先断开命令的标准输出stdout与屏幕之间的关联,找到指定的文件(若该文件不存在就新建一个),然后将这个文件关联到命令的标准输出上。随后Shell启动该命令运行。这样,该命令产生的所有标准输出信息都将写入这个文件中,而不是显示在屏幕上。

图2‑6  标准输出重定向示意图

  例2.34  输出重定向的应用:
  $  ls
   data.c   hello.c  hello.o   makefile
  $  ls > filelist
  $  ls
   data.c   filelist   hello.c   hello.o   makefile
  $  cat filelist
   data.c  
   filelist
   hello.c 
   hello.o  
   makefile
  $

  注意:上例中第2个ls命令在执行时,屏幕上没有显示。第3个ls命令表明当前目录下多了一个文件filelist,cat命令显示了这个文件,它的内容就是第2个ls命令的输出结果。

  2. 附加输出重定向
  
附加输出重定向就是将标准输出附加在一个文件的后面。
  附加输出重定向的格式为:命令 >> 文件
  附加输出重定向与标准输出重定向相似,只是当指定的文件存在时,标准输出重定向的做法是先将文件清空,再将命令的输出信息写入,而附加输出重定向则是保留文件内原有的内容,将命令的输出附加在后面。

  例2.35  附加输出重定向的应用:
  $  echo -n “Today is ” > diary
  $  cat diary
   Today is
  $  date >> diary
  $  echo “End.” >> diary
  $  cat diary
   Today is Thu May 20 20:31:10 CST 2008
   End.
  $

  上例中第1个echo命令建立了一个diary文件,并写入半行内容。date命令将输出结果附加到diary文件后。第2个echo命令向diary文件后附加了一行。最后的cat命令显示了这个文件,它的内容就是这3个命令的输出结果。

  3. 标准错误输出重定向
  
标准错误输出重定向就是将命令的标准错误输出保存到一个文件中,如图2-7所示。

图2‑7  标准错误输出重定向示意图

  标准错误输出重定向的格式为:命令 2> 文件
  例2.36  错误输出重定向的应用:
  $ ls -l
   -rw-rw-r--   1  cherry  faculty    94    May 15 20:05  data.c
   ---x--x--x   1  cherry  faculty  4680  May 12 20:15  hello
   -rw-rw-r--   1  cherry  faculty    57    May 12 09:16  hello.c
   -rw-rw-r--    1  cherry  faculty   350    May 11 10:06  makefile
  $ wc *
   6   9  94   data.c
  wc:  hello:  Permission denied
    5      7     57     hello.c
    8     58    350   makefile
    19   74    501   total

  $ wc * 2> wcerr
   6       9    94     data.c
   5       7    57     hello.c
   8      58      350   makefile
   19    74   501   total
  $ cat wcerr
   wc:  hello:  Permission denied
  $
  上例中,第1个wc命令读取当前目录下的4个文件并输出统计数据。由于用户对hello文件没有读权限,导致wc命令执行时报错。在这个wc命令的输出中,第1、3、4和5行是标准输出,第2行是标准错误输出,默认时,它们都显示在屏幕上。第2个wc命令将标准错误输出重定向到wcerr文件,此时,屏幕上不再显示错误信息。
  有时,出于调试的目的,我们更关注于程序的错误信息。用标准错误重定向可以在大量的输出信息流中捕捉住错误信息,防止它们在屏幕上一闪而过。

  4. 合并输出重定向
  
合并输出重定向就是将标准输出与标准错误输出一起写入一个文件中,如图2-8所示。

图2‑8  合并输出重定向示意图

  合并输出重定向的格式为:命令 &> 文件
  例2.37  合并输出重定向的应用:
  $   ls -l
   -rw-rw-r--   1  cherry  faculty    94    May 15 20:05  data.c
   ---x--x--x   1  cherry  faculty  4680  May 12 20:15  hello
   -rw-rw-r--   1  cherry  faculty    57    May 12 09:16  hello.c
   -rw-rw-r--  1  cherry  faculty   350  May 11 10:06  makefile
  $  wc * &> wcout
  $  cat wcout
   6    9    94    data.c
  wc:  hello:  Permission denied
   5    7    57    hello.c
   8   58   350   makefile
   19    74   501   total
  $

  本例与例不同的是,wc命令将标准输出与标准错误输出合并重定向到wcout文件。此时,屏幕上不显示任何信息,它们都被记录在wcout文件中了。

  5. 输出重定向的应用
  
输出重定向是很常用的一种命令行操作,使用输出重定向可以改变一个命令的执行效果,从而实现不同的功能。以下是几种输出重定向的典型用法:
  (1) 合并文件,并加行号:
  $ cat -n file1 file2 > file3
  用cat命令和输出重定向可以方便地实现多个文件合并。此例中,cat的输出是加了行号的file1和file2的内容(见cat命令的例2.14),重定向后,它们被写入file3中。
  (2) 快速建立文件:
  $ cat > file

  用cat和输出重定向可以方便地建立一个小文件。此例中,Shell首先建立文件file(若它不存在的话),然后运行cat。cat从标准输入读入文本,写入文件file中。
  (3) 向文件中添加内容:
  $ echo “End of file” >> file
  这是向文件中添加文本行的简单方法。这里echo命令向file文件末尾追加一行文字。如果要添加多行,可以用cat >> file命令。
  (4) 丢弃输出信息:
  $ make > /dev/null

  本例是将命令make的输出重定向到/dev/null。注:/dev/null是个特殊的设备文件,称为“空设备”,写入这个设备中的数据如同进入黑洞一样消失。这条命令执行时,make过程产生的冗长的正常输出信息被丢弃,屏幕上将只显示错误信息。

2.4.4  管道
  
管道(pipe)的功能是将一个程序或命令的输出作为另一个程序或命令的输入。利用管道可以把一系列命令连接起来,形成一个管道线(pipe line),如图2‑9所示。管道线中前一个命令的输出会传递给后一个命令,作为它的输入。最终显示在屏幕上的内容是管道线中最后一个命令的输出。

(a) 管道线“命令1 | 命令2”             (b) T形管道线“命令1 | tee 文件|命令2”
图2‑9  管道线示意图

  管道的形式为:命令1 | 命令2
         命令1 |  tee 文件 | 命令2

  管道的作用在于它把多个命令组合在一起,像流水线一样加工数据,完成单个命令无法完成的各种处理功能。恰当地使用管道可以大大提高操作的能力和效率。
  以下的例子综合了管道的几种常用方法。

  1. 浏览命令的输出
  
若一个命令的输出很多,要想有控制地观看输出结果,通常的做法是用more或less来浏览输出的内容。
  例2.38  浏览命令的输出:
  $ ls /bin | more   #翻屏查看文件列表
  $ who | more   #翻屏查看登录用户列表
  $ find . -type d | more   #翻屏查看查找的结果
  $ grep main *.c | more   #翻屏查看搜索的结果

  2. 对命令的输出进行搜索和统计
  
有时,一个命令的输出可能会很多。例如,在登录的用户很多的情况下,who命令的输出就会很长。将一个命令与grep命令结合就可以对该命令的输出进行搜索过滤,只显示所关心的信息,如某用户是否登录;将一个命令与wc命令结合就可以对该命令的输出进行统计。

  例2.39  搜索命令的输出:
  $  who
   root  tty1  May 25 11:39
   zhao  tty2  May 25 09:12
   cherry  :0  May 25 08:45
   cherry  pts/0  May 25 08:45  (:0.0)
  $  who | grep root  #看看root是否登录
   root  tty1  May 25 11:39
  $

  例2.40  统计命令的输出:
  $  ls
   bin  memo  mypaper    poem    project  test
  $  ls | wc -l   #显示当前目录下文件(包括目录)的个数
   6
  $  cat poem
   Great fleas heve little fleas
      upon their backs to bite ’em,
   And little fleas have lesser fleas,
     and so ad infinitum.
   And the great fleas themselves, in turn,
     have greater fleas to go on;
   while these again have greater still,
     and greater still, and so on.

  $ cat poem | grep fleas
   Great fleas heve little fleas
   And little fleas have lesser fleas,
   And the great fleas themselves, in turn,
      have greater fleas to go on;
  $  cat poem | grep fleas | wc –l  #统计poem文件中含有fleas的行数
     4
  $ find /bin -type f | tee save | wc -l   #将/bin下的所有普通文件的列
                  表存入save文件,并显示文件
                  个数
   76
  $

  ls命令的输出格式是每个文件名占一行。注意:屏幕上的显示结果是被Shell处理过的紧凑格式,而不是ls的实际输出格式(将ls的输出重定向到一个文件就可以看到ls实际的输出格式)。因此,在ls | wc -l命令行中,ls的输出通过管道送给wc -l命令,wc统计出的行数就是ls输出的文件的个数。


习    题
  2-1  用正确的术语(如命令名、选项、参数)辨认以下命令的组成成分:
  echo -n Hello!
  echo Hello world!
  echo echo
  2-2  如果要显示格式为“Beijing Time:hh:mm:ss”的时间,应使用什么格式参数?
  2-3  写出下列命令执行的结果:
  (1)  cd  (2)  cd ..  (3)  cd ../..  (4)  cd /

  2-4  依次执行下列命令后,当前目录的绝对路径分别是什么?
    $ cd /bin
    $ cd ../usr/share/zoneinfo
    $ cd ../../lib
    $ cd X11
  2-5  已知当前目录下有如下文件:arp, egp, ggp, icmp, idp, ip, ipip, pup, rawip, rip, tcp, udp。写出以下echo命令的输出:
  (1)  echo *ip  (2)  echo ?d*  (3)  echo [aegi]?p
  2-6  下列各对命令有何不同?
  (1)  ls /home  echo /home
  (2)  ls  echo
  (3)  ls *  echo *

  2-7下列各对命令有何不同?
  (1)  ls -l  ls -ld
  (2)  ls *  ls -d *
  2-8  解释下列信息描述的文件类型和存取权限:
  (1)  drwxr-xr-x   (2)  -rwx--x—x   (3)  crw-rw----
  2-9  已知用户主目录的访问权限是700,该目录下的memo文件的访问权限是777,其他人可以读取这个文件吗?为什么?
  2-10  设当前的文件创建掩码为037,新建立的文本文件的默认权限是什么?新建立的目录的默认权限是什么?

  2-11  给出命令,列出当前目录下名字以大写字母开头的文件,显示文件的详细信息。
  2-12  设temp是一个非空目录,说明下面3个命令的执行结果:
  (1)  rm -r temp    (2)  rm -r temp/*    (3)  rmdir temp
  2-13  给出命令,将主目录下的.profile文件复制到主目录下的backup目录下。如果目标文件已存在,提示用户是否覆盖。
  2-14  设某文件myfile的权限为-rw-r--r--,若要为其增加所有人可执行的权限,应使用什么命令?
  2-15  已知有一个普通文件,保存在主目录下的某个位置,文件名中含有mem字符串。写出查找这个文件的命令。

  2-16  给出命令,搜索主目录,删除所有扩展名为“.gif”且超过30天未被访问过的文件,在删除前提示用户确认。
  2-17  给出命令,在memo文件中搜索含有Saturday或Sunday的行,忽略大小写。
  2-18  写一条命令,统计memo文件的行数,将结果写入memo.size文件中。
  2-19  说明下面两个命令的差别:
     (1)  find -name ‘*.c’ -exec cat {}\;  (2)  find -name ‘*.c’ | cat
  2-20  说明下面3个命令的差别:
    (1)   find-name‘*.c ’-exec cat{}\;
    (2)   find-name‘*.c ’| cat
    (3)  find-name‘*.c ’ >cat

  2-21  已知一个项目的源代码文件都存放在project目录下,扩展名为“.c”或“.h”。用一个命令统计所有源代码的行数。
  2-22  分别用一个命令行实现以下功能:
  (1) 对文件data排序,将结果存入data.sort文件中。
  (2) 对文件data排序,将结果存入data.sort文件中,在屏幕上显示文件的行数。
  (3) 对文件data排序,将结果存入data.sort文件中,将文件的行数存入data.lines文件中。

linux操作系统 第02章 linux操作做基础相关推荐

  1. linux操作系统 第11章 linux系统管理

                                                                                      第11章    Linux系统管理 ...

  2. 初识Linux操作系统及常用的Linux命令

    文章目录 每日一句正能量 前言 一.Linux简介 二.Linux常用命令 每日一句正能量   平淡的生活,会带给你最简单的幸福:忙碌的脚步,会带给你最美丽的风景:真诚的祝福,会带给你最由衷的快乐! ...

  3. linux操作系统 第07章 磁盘管理

    第7章   文件管理 7.1  文件管理概述 7.1.1  文件与文件系统 1. 文件 文件是具有名字的一组相关信息的有序集合,存放在外部存储器中.文件的名字称为文件名,它是文件的标识.文件的信息可以 ...

  4. Linux操作系统实用功能,简单易操作 头歌实验一

    2022头歌平台操作系统实验一 实验(1):Linux操作系统基本使用 实验(2):Linux之C编程入门 文章目录 2022头歌平台操作系统实验一 前言 一.Linux操作系统基本使用 二.C编程入 ...

  5. linux 进程调度ppt,第章 Linux进程调度.ppt

    第章 Linux进程调度 * * SCHED_FIFO 与 SCHED_RR 的区别是: 当进程的调度策略为前者时,当前实时进程将一直占用 CPU 直至自动退出,除非有更紧迫的. 优先级更高的实时进程 ...

  6. linux教程第六章,Linux教程(第六章).ppt

    Linux教程(第六章) 1 计算机专业必修课程linux第六章 系统管理 教师: 李晓红 信息科学与工程学院计算机系 2005/8 2 主要内容 性能及内核管理 软件包管理 用户和工作组管理 设备管 ...

  7. linux操作系统源码分析,linux操作系统源代码详细分析.doc

    linux操作系统源代码详细分析.doc LINUX操作系统源代码详细分析内容简介LINUX拥有现代操作系统所有的功能,如真正的抢先式多任务处理.支持多用户,内存保护,虚拟内存,支持SMP.UP,符合 ...

  8. 韦东山 IMX6ULL和正点原子_正点原子Linux第五十七章Linux MISC驱动实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第五十七章Linux MISC驱动实验 misc的意思是 ...

  9. linux操作系统具有哪些特性,Linux系统拥有哪些特性?这些你必须知道!

    Linux操作系统不仅免费开源,同时具备了多种优势,成为了很多互联网企业首选的操作系统.那么Linux服务器操作系统有哪些特性呢?综合起来小编为大家总结了六点,一起来看看吧. 1.广泛的协议支持:Li ...

最新文章

  1. unity中单位是米还是厘米_数学单位换算公式口诀
  2. 03005_SQL查询语句
  3. web自动化测试常见面试题
  4. 五、队列(Queue)
  5. Oracle备份如何到异机还原
  6. XML 文档对象模型 (DOM)细说
  7. 中日文字编码转换_关于编码你必须知道的知识和技巧
  8. Noise,Error,wighted pocket Algorithm
  9. 冰点破解版,百度文库免费下载
  10. 嵌入式linux中文语言支持,嵌入式linux无法显示中文问题
  11. mysql 1236错误_MySQL 1236错误解决方法_MySQL
  12. 【框架-MFC】MFC 显示和隐藏 星号密码 以及如何预防被查看
  13. 微粒社会,品牌如何进行营销?
  14. html微信图片自适应,微信小程序实现图片高度自适应
  15. 计算机组成原理-错题本
  16. Swift 标准库源码 第三方,Almofire,Kingfisher,SwiftyJson,KakaJson,单元测试 request
  17. 感谢在俄勒冈州Develo的SAOs软件协会参加我的演讲“音乐背后的Web服务”的所有人...
  18. 用计算机在作文格中打单字字,描写一个字的作文
  19. 让人混淆的Person p=new Person();和Person p=null;
  20. 探秘野三坡红叶大峡谷

热门文章

  1. 关于css设置第n个元素
  2. 什么是token,如何使用token
  3. greedy、reluctant和possessive量词
  4. 什么是币圈跨链侧链?
  5. dropdownList获取值
  6. 新版一年级上册数学期末试卷
  7. MySQL 去除字符串中的括号以及括号内的内容
  8. 【论文投稿】Hindawi旗下4区Mobile Information Systems(misy)投稿详细步骤
  9. echarts实现多y轴情况下多个元素共用一个y轴
  10. AI数学基础(2)--- 霍夫丁不等式