第3章文件系统操作命令 3.1文件系统的基本概念 Linux系统中,每一个分区都是一个文件系统,都有自己的目录层次结构,而每一个文件系统具有不同的格式,这些格式决定了信息被存储为文件或目录的格式,不同的存储格式就是不同的文件系统类型。目前,Linux系统支持大部分文件系统,常见类型如下。 (1) ext2 和ext3: Linux系统默认的文件系统类型。 (2) RAMFS: 内存文件系统,速度很快。 (3) NFS: 网络文件系统,用于远程文件共享。 (4) FAT和NTFS: Windows操作系统采用的文件系统。 (5) HPFS: OS/2 操作系统采用的文件系统。 (6) PROC: 虚拟进程文件系统。 (7) ISO9660: 光盘文件系统。 Linux系统采用树状结构组织文件,为每个文件分配文件块,然后把数据存储在存储设备中。不同的文件系统用不同的方式分配和读取文件,Linux系统常用的文件分配策略为块分配和扩展分配。块分配是将磁盘上的文件根据需要分配给文件,这种方式可以避免存储空间的浪费,但当一个文件不断扩充时,就可能造成文件中的文件块不连续,从而导致过多的磁盘寻道时间,当读取一个文件时,可能会随机读取,而不是连续读取,读取效率会降低。优化文件块分配策略可以避免文件块的随机分配,尽可能实现块的连续分配,减少磁盘的寻道时间。块分配策略是当一个文件增大时为文件分配磁盘空间,而扩展分配是当某个文件的磁盘空间不足时一次性分配一连串连续的块。扩展分配可以优化磁盘寻道时间,可以成组的分配块有利于一次写入一大批数据到存储设备中,从而减少SCSI设备写数据的时间。 3.2文件的操作 3.2.1复制 cp(copy)命令的功能是将一个文件或目录从一个位置复制到另一个位置,命令格式如下。 cp[option] 源文件名目标文件名 常用的option选项有如下4种。 (1) i: interactive,交互的,在复制之前给出提示信息。 (2) r: recursive,递归的复制目录,当复制一个目录时,复制该目录中的所有内容,包括子目录中的所有文件。 (3) p: preserve,维持,保留一些特定的属性。 (4) f: force,强制的,如目标文件已经存在,不询问是否覆盖,而是直接覆盖复制。 执行复制操作时,文件名可以使用相对路径(只写文件名,不写路径,默认在工作目录下操作),也可以使用绝对路径(对其他地方的文件执行复制操作)。普通用户无权将文件复制到/root目录下,但root用户可以把文件复制到其他用户的目录下。 例3.1root用户将文件/root/mydream.txt复制到/home/jerrymos目录下。 root@liuhui-VirtualBox:~#cp mydream.txt /home/jerrymos/ mydream.txt 例3.1运行结果没有显示,可以通过ls命令查看/home/jerrymos目录下的内容来确认是否正确地把mydream.txt文件复制到了目的地。 例3.2确认复制命令的运行结果。 root@liuhui-VirtualBox:~#ls -l/home/jerrymos/ total 4 -rw-r--r-- 1 root root09月 17 13:10 1.txt -rw-r--r-- 1 root root 20599月 17 13:09 mydream.txt 例3.2运行结果显示,root用户的mydream.txt文件复制到了/home/jerrymos目录下。 3.2.2剪切和重命名 mv(move)命令既可以在不同目录之间复制文件和目录,也可以在同一个目录中重命名文件和目录,被移动或重命名的文件不会发生改变,类似于Windows系统的cut命令。 假定当前登录用户是liuhui,登录的工作目录是普通用户的家目录/home/liuhui,整理工作目录,把有关机器学习的资料放入一个新的目录deeplearning中,机器学习的资料都是以dl开头的文件。 1. 把文件从一个目录移动到另一个目录 先在工作目录/home/liuhui下创建一个新的目录deeplearning。 例3.3创建一个新的目录deeplearning。 liuhui@liuhui-VirtualBox:~$ mkdir deeplearning 例3.4查看工作目录/home/liuhui下所有以dl开头的文件。 例3.5把/home/liuhui目录中以dl 开头的文件移动到子目录/deeplearning中。 liuhui@liuhui-VirtualBox:~$ mv dladressdeeplearning liuhui@liuhui-VirtualBox:~$ mv dlreadmedeeplearning liuhui@liuhui-VirtualBox:~$ mv dlsvmdeeplearning liuhui@liuhui-VirtualBox:~$ mv dlreadtext deeplearning 也可以使用一个命令一次性移动多个文件。 例3.6用相对路径移动文件。 liuhui@liuhui-VirtualBox:~$ mv dladress dlreadme dlsvm dlreadtext deeplearning 例3.7用绝对路径移动文件。 liuhui@liuhui-VirtualBox:~$ mv dl*/home/liuhui /deeplearning 例3.6和例3.7中的命令运行结果没有显示,可以用ls命令来查看。 例3.8查看deeplearning目录中是否有刚刚移来的4个文件。 例3.9查看/home/liuhui目录下是否还有例3.5中移走的4个文件dladress、dlreadme、dlsvm、dlreadtext。 例3.9运行结果显示工作目录/home/liuhui下面没有了移走的两个文件,表明mv命令把文件移走了。 2. 在同一个目录中重命名文件 将子目录/deeplearning中的文件dlsvm重命名为dlsvmcn。 例3.10用mv命令重命名文件。 liuhui@liuhui-VirtualBox:~$ mvdeeplearning/dlsvmdeeplearning/dlsvmcn 例3.10运行结果没有显示,可以用ls命令查验更名是否成功。 例3.11查验mv命令的更名功能。 例3.11运行结果显示,子目录deeplearning 中的dlsvm文件不见了,而出现了dlsvmcn。 3. 移动文件并同时完成重命名 把deeplearning子目录下的文件dlreadme移到工作目录/home/liuhui下,同时更名为dlrdmetext。 例3.12移动并更名。 liuhui@liuhui-VirtualBox:~$ mvdeeplearning/dlreadmedlrdmetext 例3.12运行结果没有显示,用户可以用ls命令验证,也可以直接在图形界面中选择files→computer→home→liuhui命令进行查看,可以看到liuhui目录下增加了dlrdmetext文件,而deeplearning目录下的文件dlreadme不见了,如图3.1和图3.2所示。 图3.1/home/liuhui目录下多出来dlrdmetext文件 图3.2deeplearning目录下的dlreadme文件消失了 4. 重命名目录 例3.13把deeplearning目录名变更为machinelearn。 liuhui@liuhui-VirtualBox:~$ mv deeplearningmachinelearn 验证重命名的效果。 例3.14查看/home/liuhui目录下的所有子目录及文件。 例3.14运行结果显示,工作目录/home/liuhui下有一个machinelearn子目录。用ls R命令把工作目录和它的子目录的内容全部显示出来。 5. 移动目录及目录下包含的文件 工作目录/home/liuhui下有两个子目录machinelearn和hlprivacy1,把目录machinelearn下的内容移动到另一个用户jerrymos的家目录下,这相当于在/home/jerrymos目录下创建一个新目录machinelearn。这涉及两个目录,所以需要root用户的权限,先用su命令切换到root用户,然后查看这两个目录的内容移动目录。 例3.15切换到root用户。 liuhui@liuhui-VirtualBox:~$ su-root 例3.16查看移动之前两个目录的内容。 [root@localhost ~]# ls /home/liuhui /machinelearn [root@localhost ~]# ls /home/jerrymos 例3.16运行结果太多,此处省略。 例3.17移动目录。 [root@localhost ~]# mv /home/liuhui/machinelearn/home/ jerrymos 例3.17运行结果不显示,可用ls命令分别查看/home/liuhui目录和/home/ jerrymos目录下的文件,验证移动结果,再用ls命令查看验证是否把machinelearn目录下的所有内容都移动到了新位置。 例3.18验证目录的移动结果。 例3.18运行结果显示,目录/home/liuhui下没有了子目录/machinelearn,而目录/home/ jerrymos下多了一个子目录/machinelearn。 例3.19验证目录中的文件是否移动到新位置。 例3.19运行结果显示,不但目录移动到了新位置,目录下所有的文件等内容也全部移动到了新位置。 3.2.3文件的创建 1. touch命令 touch命令可以创建一个空文件,也可以同时创建多个文件,其语法形式如下。 touch 文件名 文件名可以是绝对路径名,也可以是相对路径名;文件名可以是多个,每个文件名之间用空格分隔。 1) 用相对路径创建文件 用相对路径创建文件时省略路径,就是在工作目录下创建文件。 例3.20当前用户liuhui登录后,进入默认的家目录/home/liuhui,在该目录下创建一个新文件irisdata。 liuhui@liuhui-VirtualBox:~$ touch irisdata 例3.21查看新建的文件。 liuhui@liuhui-VirtualBox:~$ ls -l 为节省篇幅,此处省略运行结果,从例3.21运行结果看,文件irisdata已经存在,文件的大小为0,创建时间为9月17 14:30。为了与后面建立的重名的文件irisdata作对比,这里在gedit编辑器中打开irisdata文件写入一些内容,然后保存。此时,irisdata文件的大小为43bytes。 2) 用绝对路径创建文件 用绝对路径创建文件将会指明在其他目录路径下创建一个新文件。 例3.22在/home/liuhui/backup目录下新建文件hldata。 liuhui@liuhui-VirtualBox:~$ touch/home/liuhui/backup/ hldata 例3.23验证例3.22是否创建成功。 liuhui@liuhui-VirtualBox:~$ ls -l /home/liuhui/backup 为节省篇幅,此处省略运行结果。例3.23运行结果显示正确创建了新文件,文件的大小为0字节,表明创建的是空文件。 3) 处理重名文件 如果新建的文件与已有的文件重命,会出现什么情况呢?在例3.23中已经在/home/liuhui/目录下有了一个文件irisdata,且文件大小为43bytes,最后修改日期为9月17 14:30。现在先在该目录下新建3个文件,便于演示如何处理重名文件。 例3.24创建3个文件,文件名分别为irisdata、mathdata、dbdata。 liuhui@liuhui-VirtualBox:~$ touch/home/liuhui/irisdata mathdata dbdata 例3.24中多个文件名之间用空格分隔,命令的运行结果不显示,可以查看创建的结果。 例3.25重名文件的处理。 例3.25运行结果显示,新创建mathdata和dbdata两个文件的时间是9月17 15:31,文件大小是0; 而irisdata文件的创建时间也是9月17 15:31,文件的大小是43bytes。但是第一次在例3.20中创建irisdata文件的时间为9月17 14:30,,说明第二次创建的重名的空文件时会把已经存在的文件的创建时间修改为最后一次创建时间,或者说是把第一次创建的文件的访问时间修改为最后一次的时间,但文件内容还是第一次创建时形成的内容。 2. file命令 在Linux系统中,文件的扩展名并不代表文件的类型,而打开不同类型的文件使用的命令也不一样,所以在打开文件之前,需要先确定文件的类型。确定文件类型的命令是file,命令的语法格式如下。 file 文件名 要查看文件类型,需要先查看用户的家目录中的所有文件。 例3.26用ls F命令查看普通用户liuhui的家目录下的文件。 由例3.26运行结果可见,用户liuhui家目录下有很多目录和文件,用file命令来查看文件的类型。 例3.27查看Windows系统文件的类型。 liuhui@liuhui-VirtualBox:~$ filet1.txt t1.txt: ISO-8859 English Text,with long lines,with CRLF line terminators 例3.27运行结果显示,该文件是一个内容为英文的正文文件,详细地说明了文件的长度、回车结束符号等信息。 例3.28查看Linux系统文件的类型。 liuhui@liuhui-VirtualBox:~$ file mathdata mathdata:UTF-8 Unicode Text 例3.28运行结果只显示Unicode码的正文,显示的信息比较少。 例3.29查看目录的类型。 liuhui@liuhui-VirtualBox:~$ file deeplearning deeplearning:directory 从上述几个例子可以看出,file命令的运行结果与ls F命令的显示结果非常类似,差别只是file的信息更详细而已。 3.2.4编辑 1. gedit gedit是图形化的文本编辑工具,是一个GNOME桌面环境下兼容UTF8的文本编辑器。gedit使用GTK+编写而成,十分简单易用,有良好的语法高亮,对中文支持度很好,支持包括GB2312、GBK在内的多种字符编码。gedit是一个自由软件,是Linux系统下的一个纯文本编辑器,也可以认为是一个集成开发环境(Integrated Development Environment,IDE), 它会根据不同的语言高亮显示关键字和标识符,类似于Windows系统下的一个文本编辑环境。 在终端的命令行方式下,输入命令gedit,按Enter键,就可以启动gedit编辑器。 例3.30使用gedit编辑文件hldata1,运行界面如图3.3所示。 liuhui@liuhui-VirtualBox:~$ gedit hldata1 图3.3gedit的运行界面 gedit的使用非常简单,其支持键盘和鼠标的复制粘贴操作。 2. vi vi是UNIX和Linux系统内嵌的标准的全屏正文编辑器,是以命令行方式输入的正文编辑器,它可以在图形界面没有启动的情况下工作。如果系统出现问题,图形界面将无法启动,使用vi进行系统维护就是唯一的方法。 简单的程序编写,使用gedit工具就可以完成任务; 在编写复杂的程序和系统无法正常启动的情况下,使用vi更合适。但是vi的使用方法复杂,更适合于专业人员使用,只有经过反复的练习才可以真正掌握。 vi是visual interface to the ex editor的前两个单词的首字母,ex是UNIX系统上的一种行编辑器。当用vi 编辑一个正文文件时,vi 将文件中的所有正文放入一个内存缓冲区,后续的操作都是在内存缓冲区进行的。vim是vi improved的缩写,可以认为vim是个程序开发工具,而不仅仅是一个正文编辑器。 在终端的命令行方式下,可以使用vi命令来启动vi编辑器以创建、修改或浏览一个或多个正文文件。vi命令的语法格式如下。 vi [选项][文件名] 常用的选项是r和R,使用r选项可以恢复退出编辑时没有保存的文件,语法格式如下。 vi-r文件名 R选项以只读方式打开文件,语法格式如下。 vi-R文件名 使用vi打开文件时,如果该文件已经存在,vi将开启这个文件并显示该文件的内容; 如果文件不存在,则在所编辑的内容第一次存盘时创建文件,并把已经编辑的内容保存进文件。 图3.4vi编辑器的使用 例3.31使用vi编辑器打开文件mydream,运行界面如图3.4所示。 liuhui@liuhui-VirtualBox:~$ vi mydream 打开vi编辑器以后,需要先按Insert键进入输入状态,然后才可以正式输入文字; 需要删除一个字符时,需要先按Delete键,然后用Delete键或Backspace键删除一个字符; 如果要删除一行,先按Delete键,然后连按两次D键即可把光标所在行删除。 要退出vi编辑器,先按Esc键,再输入冒号:,窗口最下面便会出现 : 提示符,最后输入字母wq或q并按Enter键,就可以退出vi编辑器了。 3.3文件内容处理 3.3.1内容浏览 1. cat命令 命令cat(concatenate)可以实现如下所述3个功能。 (1) 第1个最常用的功能是在显示器上列出文件的内容,如果cat命令后面的文件是存在的,则该命令会以不停顿的只读方式显示整个文件的内容。 例3.32用cat命令显示正文内容。 命令运行后,文件的内容就会直接显示在终端的窗口中,但只可以查看,不可以编辑。 (2) 第2个功能是从键盘创建一个新文件,命令格式如下。 cat>filename 按Enter键后,光标会停留在下一行开始处,等待用户在终端上从键盘输入字符。>为重定向符,表示把输入的内容输入文件中。输入完毕,按Ctrl+D快捷键退出编辑,输入的内容同时保存到新创建的文件中。 例3.33创建新文件hlnew。 (3) 第3个功能是将几个文件合并为一个文件,命令格式如下。 cat file1 file2> file 例3.34用cat命令合并文件。 用cat命令实现合并文件,运行结果没有显示,再使用cat命令在终端上显示合并后的新文件的内容,可以发现确实把两个文件纵向合并成了一个文件。 cat命令用于显示正文文件时可以正常显示,但是如果想显示二进制文件,系统会出现不稳定、终端突然死机的情况。 2. head命令 head命令默认显示文件的前10行,可以使用参数 n来指定显示的行数。 例3.35显示系统文件passwd的前10行。 例3.36指定只显示文件中前5行的内容。 liuhui@liuhui-VirtualBox:~$ head -n 5/etc/passwd 或者 liuhui@liuhui-VirtualBox:~$ head -5/etc/passwd 例3.36运行结果省略,可以参照例3.37。 例3.37用line选项指定要显示的行数。 3. tail命令 tail命令可以显示文件最后几行的内容,默认显示最后10行的内容; 也可以用-n和+n指定显示行数。-n表示从文件末尾算起的n行; +n 表示从文件的第n行算起到文件结尾的内容。 例3.38显示最后10行。 例3.39用n选项设定显示最后两行。 liuhui@liuhui-VirtualBox:~$ tail -n 2 deeplearning/mydream 运行结果省略,参见例3.41。 例3.40用line选项设定显示最后3行。 liuhui@liuhui-VirtualBox:~$ tail --line 3 deeplearning/mydream 例3.41用数字参数设定只显示最后两行。 4. more命令 如果正文的内容很长,用前文介绍的命令浏览文件时不太方便,可以使用more命令将文件内容在屏幕上一次只显示一页,需要时可以上下翻页。在执行more命令时,每次在显示器上显示一页的内容,并在页面的底部出现“more(n%)”标记信息(n%表示已经显示的内容占总内容的百分比),可以使用键盘上的如下按键进行操作。 (1) 空格键: 向前(向下)移动一个屏幕。 (2) Enter键: 一次移动一行。 (3) B: 往回(向上)移动一个屏幕。 (4) H: 显示帮助菜单。 (5) /字符串: 向前搜索这个字符串。 (6) N: 发现这个字符串的下一个出现。 (7) Q: 退出more命令并返回操作系统提示符下。 (8) V: 在当前行启动/usr/bin/vi。 例3.42使用more命令查看长文件。 liuhui@liuhui-VirtualBox:~$ more hldata more命令运行结果与cat命令很相像,但more命令是一页一页显示,按空格键可以翻到下一页,按B键向前回退一页,按Q键退出显示。为了节省篇幅,这里省略了运行结果。 3.3.2内容搜索 1. grep命令 grep是global/regular expressions/print的缩写,grep命令能够在一个或多个文件的内容中搜索某一个特定的字符模式(character pattern),也称为正则表达式(regular expression)。一个模式可以是一个单一的字符、一个字符串、一个单词或一个句子。 一个正则表达式描述一组字符串的一个模式,正则表达式的构成模仿了数学表达式,通过使用操作符将较小的表达式组合成一个新的表达式。一个正则表达式既可以是一些纯文本文字,也可以是用来产生模式的一些特殊字符。grep命令支持如下几种正则表达式的元字符(regular expression metacharacter),即通配符。 (1) *: 匹配0个(即空白)或多个字符。 (2) .: 匹配任何一个字符,而且只能是一个字符。 (3) [xyz]: 匹配方括号中的任意一个字符。 (4) [^xyz]: 匹配不包括方括号中的字符的所有字符。 (5) ^: 锁定行的开头。 (6) $: 锁定行的结尾。 在基本正则表达式中,元字符*、+、{、|、(和 )失去了原义,如果要恢复其原义,要在之前冠以反斜线\,即\*、\+、\{、\|、\(、和\),这类似于其他语言中的转义字符。 使用grep命令时,包含指定字符模式的每一行都会显示在显示器上,但是并不改变原有文件的内容。grep命令的语法格式如下。 grep选项模式文件名 grep命令中常用选项如下。 (1) c: 仅列出包含模式的行数。 (2) i: 忽略模式中的字母大小写。 (3) l: 列出带有匹配行的文件名。 (4) n: 在每行的最前面列出行号。 (5) v: 列出没有匹配模式的行。 (6) w: 把表达式作为一个完整的单词来搜寻。 在用户liuhui的家目录下有一个backup子目录,里面有很多备份文件,包括Linux系统下书写的代码、Shell程序、txt文件等。 例3.43在pythontrain文件中搜索含有Python字样的内容,搜索模式是Python。 例3.43运行结果显示了所有含有Python字样的文字所在的行。如果想统计共有多少行,可以使用选项c。 例3.44统计满足条件的行数。 Linux系统是区分大小写的,如果希望在搜索时不区分大小写,可以使用 i选项忽略大小写。 例3.45在pythontrain文件中搜索含有Python字符的内容,忽略大小写。 liuhui@liuhui-VirtualBox:~/backup$ grep -iPython pythontrain 例3.45运行结果省略。 例3.46在pythontrain文件中搜索以字符In开头的数据行。 backup子目录中有一个员工工资的数据文件selary,下面搜索所有工资在1000~1990之间的数据行,在grep命令中,1..0表示以1开头,以0结尾,中间有两个数字的字符串。 例3.47匹配模式为1..0的搜索。 liuhui@liuhui-VirtualBox:~/backup$grep'1..0'selary 例3.48搜索首字母不是1或2 的数据行。 liuhui@liuhui-VirtualBox:~/backup$ grep -v[12]…selary 在Linux系统中,因为系统管理和维护的需要,经常需要用grep命令搜索系统配置信息。 例3.49进入/etc目录查看/etc目录下的相关信息。 liuhui@liuhui-VirtualBox:~/backup$ cd /etc 例3.50在当前目录下搜索group、passwd、hosts文件中含有root的文件名。 liuhui@liuhui-VirtualBox:etc$ grep -l rootgrouppasswdhosts 例3.51用ls命令验证例3.50的运行结果。 例3.52用head命令列出group文件中前两行信息,以确认文件中确实含有root字符。 liuhui@liuhui-VirtualBox:etc$ head-2 group 例3.53用head命令列出passwd文件中前两行信息,以确认文件中确实含有root字符。 例3.54用cat命令列出hosts文件中的信息,以确认文件中确实不含有root字符。 例3.54运行结果显示,hosts文件中确实不含有root字符,所以在例3.50的结果中没有hosts文件。 2. find命令 使用find命令可以在文件路径中查找文件和目录,可以使用文件名、文件的大小、文件的属主、修改时间和类型等条件来进行搜索,当find命令找到了与搜索条件匹配的文件时,系统会将满足条件的每一个文件都显示在显示器上。find命令的语法格式如下。 find pathnamesexpressionsactions (1) pathnames: find命令所查找的目录路径。例如,用.来表示当前目录,用/来表示系统根目录。 (2) expressions: 由一个或多个选项定义的搜寻条件。如果定义多个选项,find命令将使用它们逻辑与(and)操作的结果,将列出满足所有条件的结果。 find命令中常使用的条件表达式expressions如下。 name: 按照文件名查找文件。文件名可以使用元字符,但是要放在双引号中。 size [+|-]n: 查找文件大小大于或等于+n(小于-n)的文件。默认情况下,n代表512字节大小的数据块的个数。 user: 按照文件属主来查找文件。 group: 按照文件所属的组来查找文件。 mtime -n +n: 按照文件的更改时间来查找文件, -n表示文件更改时间距现在n天以内,+n表示文件更改时间距现在n天以前。 (3) actions: 当文件被搜寻到以后需要进行的操作,默认将搜寻结果显示在显示器上。 在find命令中,可以使用如下的actions(动作表达式)。 exec命令{ }\;: find命令对匹配的文件执行该参数所给出的Shell命令。相应命令的形式为'command { }\;',注意{ }和\ ; 之间必须有空格,{}之间无空格,\和; 之间无空格。花括号{} 表明文件名将传给前面表达式所表示的命令。{} 后面加空格,\ 和; 表示命令的结束。 ok命令{ }\;: 和exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的Shell命令,在执行每一个命令之前都会给出提示,让用户来确定是否继续执行。 print: find命令将匹配的文件输出到标准输出。 ls : 显示当前路径名和相关的统计信息。 例3.55在当前用户liuhui的家目录中,通过文件名查找文件内容含有cat字样的文件。 例3.55运行结果较多,只截取了一部分。运行结果显示工作目录下含有cat字样的所有文件。 例3.56文件名的通配符的使用。 例3.57文件名的通配符的使用。 为了节省篇幅,这里只截取了一部分运行结果。运行结果表明,3种含有通配符的不同书写方法,对运行结果没有影响。但建议还是使用把所有文件名都括在双引号中的写法,因为有些系统可能运行结果不同。 假如用户liuhui的工作目录中有些文件已经过时,以后不用了,但又不能完整记住所有文件名,就可以用find命令先搜寻出这些文件,然后删除。 例3.58搜寻并删除工作目录下含有huibian字样的文件。 此命令须注意rm{}\; {}和\; 之间没有空格,其他地方有空格。 命令执行后系统无提示,可以用ls命令查看目录的内容来验证是否真正删除了。 例3.59验证例3.58是否真正删除了过时的文件huibian。 运行结果表明确实删除了过时的文件。例3.58的删除操作在删除之前并没有给用户提示,让人觉得突兀,也不放心。在命令中加入ok动作表达式,可以强制系统在执行ok 后面的动作时给出提示。 例3.60删除动作执行前给出提示。 运行时根据提示输入y,表示同意删除,输入n表示不同意删除。执行以后没有显示结果,用户可以再用ls命令查看验证。 例3.61在工作目录中查看过去3天内没有修改过的文件,即搜寻3天之前修改的文件。 liuhui@liuhui-VirtualBox:~$ find.-mtime +3 因为工作目录下修改时间大于3天的文件太多,为了节省篇幅,这里省略例3.61运行结果。 例3.62搜寻backup目录中3天之内修改过的文件。 例3.63搜寻3天之内被访问过的文件。 例3.63运行结果没有显示文件的时间信息,可以利用ls l命令查看文件的详细信息进行验证。 例3.64查看文件的时间信息。 liuhui@liuhui-VirtualBox:~$ ls -l /home/liuhui/backup backup目录下访问时间小于3天的文件太多,为了节省篇幅,这里省略了例3.64运行结果,运行结果可以与例3.63做对照,可以看出例3.63中显示了文件的访问时间确实是3天之内的。 3.3.3内容统计 使用命令wc(word count)可以统计一个文件中内容的行数、单词数和字符数,语法格式如下。 wc [options] file-list 其中,options是选项,常用选项如下。 (1) c: 统计文件字节数。 (2) m: 统计文件字符数。 (3) l: 统计文件行数。 (4) L: 统计文件最长行的长度。 (5) w: 统计文件单词数。 如果命令中没有使用任何选项,则将文件中的行数、单词数和字符数全部显示出来。 例3.65统计工作目录下hldata1文件内容的行数、单词数和字符数。 例3.65运行结果按行数、单词数和字符数的顺序显示了各项的大小。 前面学习过诸如who、whoami、users等获取用户信息的命令,如果想统计本机上有几个用户,就可以使用wc命令的统计功能。因为在/etc/passwd文件中,每个用户都有且只有一行记录,所以/etc/passwd文件内容的行数就是用户的个数,使用l选项可以只获取数据的行数,即用户数。 例3.66统计用户数。 例3.66运行结果显示了当前有39行数据,即有39个用户。用户可以用cat命令直接查看passwd文件,也可以在图形界面中直接打开/etc/passwd文件进行查看,可见里面确实有39个用户,系统创建的用户在前面记录,安装系统时创建的普通用户和用adduser命令增加的用户在文件的最后几行记录。 例3.67统计联机字典中单词的个数。 Linux的联机字典存储在/usr/share/dict/words文件中,每个单词占据一行,文件的行数就是单词的个数。 3.3.4内容比较 1. diff命令 diff是单词different的缩写,用来比较两个文件内容的差别,运行结果的第1行以<开始,显示第1个文件的内容。第2行以>开始,显示第2个文件的内容。diff命令经常用在软件升级时,对比新的配置文件和旧的配置文件之间的不同。 diff命令是以逐行的方式比较文本文件内容的异同之处,如果指定比较的是目录,diff命令会比较两个目录下名字相同的文本文件的内容,但不会比较其中的子目录。 在用户liuhui的家目录下有两个文件mydream和newdream,先查看这两个文件的内容。 例3.68查看mydream文件的内容。 例3.69查看newdream文件的内容。 两个文件比较长,后面部分都是相同的,故例3.68和例3.69运行结果省略了后面部分的显示。 例3.70用diff命令比较这两个文件的不同。 2. sdiff命令 sdiff(SidebySide Difference)命令会把比较的结果显示出来,符号的左侧显示第1个文件的内容,|符号的右侧显示第2个文件的内容; 如果第1个文件还有内容而第2个文件没有内容了,则用符号<表示; 如果第2个文件还有内容而第1个文件没有内容了,用符号>表示。因为比较的文件每行内容较长,所以第2个文件的内容另起一页显示了,如例3.71所示。 例3.71用sdiff命令比较文件。 从运行结果来看,sdiff命令的显示结果比diff命令的结果更清晰简单,但是如果两个文件内容很多,而且差别又很少,sdiff命令的运行结果就不容易阅读,还是使用diff命令更好一些。 3.3.5内容转换 1. Tab转换为空格 expand命令用于将文件的制表符(Tab)转换为空格符(Space),默认一个Tab对应8个空格符,并将结果输出到标准输出。若不指定任何文件名或所给文件名为 ,则expand命令会从标准输入读取数据。用户也可以使用输入输出重定向符指定读入和输出的文件名。 expand命令语法格式如下。 expand [options][file] 常用选项如下。 (1) i,initial: 不转换非空白符后的制表符。 (2) t,tabs=NUMBER: 指定一个Tab替换为多少个空格,而不是默认的8。 例如,在liuhui用户的家目录中有一个文件windata,文中的分隔符是Tab键,将Tab转换为空格,首先要在命令中使用A选项查看该文件。 例3.72使用A选项查看文件中的分隔符类型。 例3.72运行结果中的^I就表示分隔符是Tab键,行尾的$表示是以Enter键换行的。下面用expand命令把Tab分隔符转换为空格符,同时把转换以后的内容重定向输出到文件windata.spaces中。 例3.73把Tab分隔符转换为空格符。 liuhui@liuhui-VirtualBox:~$ expand windata>windata.spaces 例3.73运行结果没有显示,可以使用cat命令查看转换以后的文件内容。 例3.74显示分隔符类型。 例3.74运行结果的分隔符看不到特殊符号,表明是空格分隔符。 2. 文件内容的格式化转换 fmt命令可以将文件格式化成段落,就是定义一行文字的格式,其语法形式如下。 fmt [-WIDTH] [OPTION]... [FILE]... 每行的宽度使用wn选项来定义,w是width的第1个字母,n是字符的数目,系统默认是75个字符,也可以用u选项将文件中的空格统一化,即每个单词之间使用一个空格分隔,每个句子使用两个空格分隔。 先对例3.72中的文件windata.spaces做一些处理,在单词之间无规律地添加不同数目的空格,然后统一空格字符的个数。 例3.75统一空格字符的个数,每行48个字符。 liuhui@liuhui-VirtualBox:~$ fmt -u -w48 windata.spaces > windata.fmt 例3.75运行结果没有显示,再次使用cat A命令查看文件内容。 例3.76查看统一以后的文件。 仔细观察例3.76的运行结果,可以看出每个单词之间都由一个空格分隔,多余的空格去掉了; 每个句子以两个空格分开,段落以$作为结束符。 3.3.6文件归档、压缩及解压缩 1. tar命令 为了保证文件的安全,经常要对文件进行备份和归档。Linux系统的标准归档命令是tar,tar命令的功能是将多个文件(包括目录)放在一起存放到一个磁带或磁盘归档文件中,并且将来可以根据需要只还原归档文件中某些指定的文件。tar命令默认不进行文件的压缩,但tar命令本身支持压缩和解压缩算法,内部的压缩和解压缩算法是gzip和gunzip或bzip2和bunzip2。 tar命令的语法格式如下。 tar [参数] 文件名 归档后的文件名要使用相对路径。在tar命令中必须至少使用如下选项中的一个。 (1) c: 创建一个新的归档文件。 (2) t: 列出归档文件中内容的目录。 (3) x: 从归档文件中抽取文件。 (4) f: 指定归档文件或磁带。 tar命令中还有以下3个可选的选项。 (1) v: 显示所打包的文件的详细信息。 (2) z: 使用gzip压缩算法来压缩打包后的文件。 (3) j: 使用bzip2压缩算法来压缩打包后的文件。 tar命令中所有选项之前都不能使用前导符号。 普通用户liuhui登录到默认的家目录,家目录中有一个子目录Pictures,含有若干图片文件,现在把这个子目录归档成pictures.tar文件,使用c选项创建一个新的归档文件,使用v选项在创建的过程中显示所有打包的文件和目录,使用f选项指定归档的文件名为pictures.tar。 例3.77归档新文件。 例3.77运行结果显示了归档后新文件中包含的所有文件和目录,最后一个文件是个截图文件,使用的默认文件名比较长。也可以使用tar命令显示pictures.tar中包含的所有文件。 例3.78用t选项列出归档文件包含的所有文件。 2. 恢复文件 接下来再把归档打包的文件解开,并恢复到原来的位置,使用tar命令的xvf选项在工作目录中抽取打包的文件,所以需要将工作目录切换到打包时所在的目录。为了更加清楚地演示打包文件的恢复过程,先把原来Pictures子目录的所有内容全部删除。 例3.79使用rm r命令删除目录和目录中的所有内容。 liuhui@liuhui-VirtualBox:~$ rm -r Pictures 例3.79运行结果没有显示,可以使用ls命令验证查看。 例3.80验证工作目录中没有Pictures子目录。 例3.80运行结果表明目录中只有归档文件pictures.tar,也可以在图形界面下直接查看有无目录Pictures。 例3.81恢复归档时被删除的原始文件。 例3.81运行结果表明被删除的文件通过事先归档的文件又被恢复到了工作目录下。 3. gzip命令 在Linux系统中有两组常用的压缩命令,第1组是gzip和gunzip,第2组是bzip2和bunzip2。gzip对正文文件的压缩比一般超过75%,通常bzip2对归档文件的压缩比要优于gzip,比较新的Linux版本才支持bzip2和bunzip2。 gzip命令可以用来压缩文件,压缩后的结果会存在一个文件中,使用原来的文件名加上.gz作为扩展名,压缩文件会保留原文件的访问及修改时间、所有权和访问权限,原文件将会从文件结构中删除。gzip命令只能对文件进行压缩,对目录不能压缩。 gzip命令的语法格式如下。 gzip [选项] [压缩文件名…] gzip命令的几个经常使用的选项如下。 v: 在屏幕上显示文件的压缩比。 c: 保留原文件并新创建一个压缩文件。 1) 压缩、解压缩普通文件 普通用户liuhui的家目录/home/liuhui下有一个目录hlprivacy1,该目录下有Linux系统下编辑的多个文件和一个目录linuxdata,用gzip命令来压缩文件,压缩之前先查看文件的详细信息。 例3.82查看要压缩的文件。 例3.83压缩文件并查看已经压缩的文件。 例3.83运行结果表明,目录下确实生成了一个名为d1.txt.gz的压缩文件,但是原有的d1.txt文件不见了,文件的大小也发生了变化,且变小了,证明了gzip确实将文件进行了压缩。该目录下还有一个d1.txt~文件,这表明在hlprivacy1目录下曾经对这个文件d1.txt做过修改,或者刚刚删除了这个文件,也就是“~”代表草稿文件,现在已经保存完毕了,可以不必理会它。另外要注意,在Linux中,文件的后缀不表示类型,后缀是文件名的一部分,所以在输入时要连后缀一起输入作为文件名。 利用gunzip命令可以将原文件恢复。 例3.84解压文件。 liuhui@liuhui-VirtualBox:~$ gunzip d1.txt.gz 例3.84运行结果没有显示,可以用ls命令查看验证。 例3.85查看解压后的文件。 例3.85运行结果表明,被压缩的文件d1.txt.gz已经被恢复成原文件d1.txt了,与例3.82的运行结果比较可以发现恢复的文件和原来的一模一样。同时,压缩形成的文件d1.txt.gz消失了。能否在压缩文件的同时保留原始文件呢? 例3.86压缩文件时保留原文件play.txt。 例3.86运行过程中会显示压缩比,这是由于使用了v选项; 运行结果表明,需要用重定向符指定压缩后的文件,否则不能正常压缩,且有乱码提示。 例3.87验证压缩操作后是否保留了原文件。 例3.87运行结果可见,工作目录下除了原文件play.txt以外,还有一个压缩文件play.txt.gz。 2) 压缩图像文件 对于普通文件,经过压缩后文件变小了很多,压缩比可达32%; 对于图像等以二进制形式保存的文件同样也可以压缩。 例3.88压缩图像文件。 压缩图像文件的运行过程比较慢,结果表明只压缩了0.9%。对于图像文件,一般不执行压缩操作,因为图像文件的数据格式,不管是jpg、bmp,还是png、gif,本身就已采用了压缩格式。 3) 压缩目录 在文件传送中,有时一次需要传送多个文件,在Windows系统中可以把多个文件放在一个文件夹中,压缩后变为一个文件再传送,方便双方收发。在Linux系统中是否也可以对目录进行压缩呢? 普通用户liuhui的家目录/home/liuhui下有一个目录hlprivacy1,该目录下有Linux系统下编辑的多个文件和一个目录linuxdata,里面有多个文件,对这个目录执行压缩操作。 例3.89压缩目录。 例3.89运行结果提示不能压缩目录。 4. bzip2命令 bzip2采用新的压缩算法,压缩效果比gzip压缩算法更好。若没有加上任何参数,bzip2命令压缩完文件后会产生后缀为.bz2的压缩文件,并删除原始的文件。bzip和gzip一样,都不支持压缩目录。其语法格式如下。 bzip2 [参数][文件名] 常用参数如下。 (1) r : 查找指定目录并压缩或解压缩其中的所有文件。 (2) k: 压缩并保留原文件。 (3) c或stdout: 将压缩与解压缩的结果送到标准输出。 (4) d或decompress: 执行解压缩。 (5) f或force: bzip2在压缩或解压缩时,若输出文件与现有文件同名且没有参数,默认不会覆盖现有文件,使用参数f可以强制覆盖原文件。 普通用户liuhui登录到目录/home/liuhui/hlprivacy1,该目录下有Linux系统下编辑的文件tomcat1.txt,用bzip2命令来压缩该文件之前先查看文件的详细信息。 例3.90查看要压缩的文件。 例3.91用bzip2命令压缩文件。 例3.91运行结果没有显示,可以使用ls命令来查看,也可以使用图形界面,在桌面上双击Files图标直接查看文件,发现tomcat1.txt文件没有了,出现了tomcat1.txt.bz2文件,如图3.5所示。 图3.5bzip2命令的执行结果 例3.92解压例3.91中压缩的文件。 例3.92运行结果没有显示,可以使用ls命令来查看,也可以使用图形界面,在桌面上双击Files图标直接查看文件,发现tomcat1.txt.bz2文件没有了,出现了tomcat1.txt.。 例3.93压缩文件时保留原文件。 liuhui@liuhui-VirtualBox:~$ bzip2 -kjerrymos1 例3.93运行结果没有显示,可以用ls 命令验证查看。 例3.94查看原文件是否被保留。 例3.94运行结果表明原文件被保留了。 3.4文件输入输出 在系统默认情况下,Shell从键盘读命令的输入,并将命令的输出显示到显示器上。但在命令或者Shell脚本中,使用输入输出重定向符可以改变实际操作时读入数据和显示数据的方式。 3.4.1文件描述符 文件描述符是Linux系统内部使用的一个文件代号,它决定从哪里读入命令所需的输入和将命令产生的输出及错误显示送到哪里。 文件描述符有0、1和2,共3个编码,具体含义如下。 (1) 0: 标准输入,文件描述符的缩写为stdin。 (2) 1: 标准输出,文件描述符的缩写为stdout。 (3) 2: 标准错误(信息),文件描述符的缩写为stderr。 这些号码存储在/dev/std*系统文件中,可以用ls命令来查看。 例3.95查看文件描述符。 例3.96标准输出和标准错误信息。 3.4.2输入输出重定向和转换 1. 输出重定向 >符号为输出重定向符号; >>也是输出重定向符号,二者的区别如下所述。 (1) >: 覆盖原文件的内容,每次都删除原有文件的内容,从文件的开头写入数据。 (2) >>: 在原文件之后追加内容,原文件的内容保留,新增加的内容紧跟在原文件内容的后面。 输出重定向命令语法如下。 command>filename command>>filename 功能说明: 把command命令的运行结果写入filename文件中,而不是把命令的执行结果显示在显示器上。 例3.97从/etc目录开始搜寻名为passwd的文件,在屏幕上只显示标准错误信息,将标准输出重定向到一个名为output.std的文件中。 例3.97运行结果表明,第1次在普通用户liuhui的家目录下执行查询/etc目录下的文件的find命令时,系统提示无权操作的错误信息,因为命令中只规定把标准输出重定向到output.std文件中,没有定义系统错误信息的输出,所以使用默认操作输出到显示器上。更换为root用户后,再执行find /etc命令,显示器上没有任何运行结果; 于是使用cat命令查看重定向的文件output.std,可以看到查找到的passwd文件在/etc目录下有3处。 例3.98将find命令的标准输出写入output.std文件,将标准错误信息写入err.std文件。 2. 输入重定向 使用<符号可以从文件中读取数据到命令中,断开键盘和“命令”的标准输入之间的关联,然后将输入文件关联到标准输入。 输入重定向命令语法如下。 command < filename 功能说明: command命令的输入来自filename文件。 例3.99从文件中读取数据存入变量中。 例3.99中,从inpt4文件中读取一行数据存入变量var1,然后用echo输出变量的值加以验证。 3. 转换命令 输入重定向经常用于对文件格式的更改,例如从Windows系统中传入的文件,以回车符\r和换行符\n结束一行; 而在Linux系统中,使用\n结束一行。从Windows系统导入文件到Linux中时,不可能手工修改结束符号,于是Linux提供了tr(translate)命令,可以转换、压缩和删除来自标准输入的字符,并将结果写到标准输出设备上。tr命令的输入不接受文件名形式的参数,即不能用文件名作为它的输入参数,只能以输入重定向<或者管道|来指定输入的数据来源。 tr命令的语法如下。 tr OPTION… SET1 [SET2] 一个SET就是一串字符,包括特殊的反斜杠转义字符。 tr命令常用选项如下。 (1) d或delete: 删除所有属于第1个字符串SET1的字符。 (2) s或squeezerepeats: 用第2个字符串SET2代替第1个字符串SET1,或者把连续重复的字符以单独一个字符表示。 (3) t或truncateset1: 删除第1个字符串SET1较第2个字符串SET2多出的字符。 tr命令通常与管道或其他命令结合使用,可以执行删除重复字符、将大写转换为小写以及替换和删除基本字符等操作。 例3.100查看从Windows系统传来的文件possible.txt中的结束符。 例3.100运行结果表明,Windows系统下的文件以\r和\n作为结束符,结果以^M$标注,并且最后一行没有换行符。Linux系统下的结束符只有\n一个。 例3.101更改结束符并存为新文件。 例3.101中,从possible.txt文件读取数据,利用tr d命令删除\r字符,把删除\r字符以后的文件以新文件保存到poss3.lnx文件中,然后再查看结束符,确实变成了$,即只有\n作为结束符。 删除\r字符,还可以以tr s命令来实现,即把\r\n替换为\n,如例3.102所示。 例3.102用tr s命令把\r\n替换为\n并存入新文件poss2.lnx中。 例3.102运行结果表明,用\n代替\r\n后,poss2.lnx文件以\n作为结束符,结果以$标注。 例3.103将jerrymos1文件中所有大写字母转换成小写并保存到新文件jrymos中。 执行命令后,可以用cat命令查看转换以后的文件中是否还有大写字母,也可以在图形界面中直接打开文件查看。 例3.104删除文件中的多个空格,以一个空格代替之。 3.4.3剪切和粘贴 1. 剪切 剪切(cut)命令是从一个文件中剪切掉某些正文字段,并将它们送到标准输出显示。实际上cut命令是一个文件维护的命令,其语法格式如下。 cut [选项]…[文件名]… 其中常用的选项如下。 (1) f: 定义要截取的字段列。 (2) c: 要剪切的字符。 (3) d: 说明字段的分隔符(默认为Tab)。 例3.104已经把db2文件中的多个空格分隔符整理为一个空格符作为分隔符后存入新文件dbdt2中,下面取出文件中的某一列数据,在命令中用d选项说明分隔符为空格。 例3.105从dbdt2文件中选取第2个字段的数据并存入文件dbname文件中。 文件dbdata中的数据以逗号“,”作为分隔符,现在想取出里面第1列stdid的数据,则需要在命令中指定分隔符为“,”。 例3.106取出dbdata文件的第一列stdid的数据,并存入dbid文件中。 2. 粘贴 粘贴(paste)命令主要用于将多个文件的内容合并输出,合并动作为按行将不同文件的行信息放在一行,即把每个文件的一行数据作为一列,把多个文件在宽度上合并在一起。默认情况下,不同文件的数据用空格或Tab键进行分隔,并把合并的结果写到标准输出上。 paste命令的语法格式如下。 paste -d -s -file1 file2 paste命令的选项含义说明如下。 (1) d: 指定不同于空格或Tab键的域分隔符。 (2) s: 将每个文件合并成行而不是按行粘贴。 (3) : 使用标准输入。 如果命令中没有文件名,或文件名使用了,paste将从标准输入设备读入数据,将多个文件合并成一个文件; 如果在命令中使用了d选项,将更改输出的分隔符,默认分隔符是Tab字符。 例3.107把例3.105和例3.106中生成的文件dbname和dbid横向合并,合并两个文件成一个文件,两列数据之间以#分隔。 例3.108把第1个文件的所有数据放一行,第2个文件的所有数据放另一行。 由例3.108可以看出,paste命令是对文件在宽度上做扩展,即被合并的每个文件的数据作为一列,从左向右排列成新文件。前文介绍的输出重定向>、>>和 cat f1 f2>newfile是在文件行上的合并,使文件长度增加,即纵向合并。 3.4.4排序和管道操作 1. 排序 排序(sort)命令的功能是对正文进行排序并将结果送到标准输出设备,原有文件的内容不会发生变化,其正文数据既可以是一个文件,也可以是另一个命令的输出。 sort命令的语法格式如下。 sort [选项] [文件名] sort命令中常用的选项如下。 (1) r: 进行反向排序(降序)。 (2) f: 忽略字符的大小写。 (3) n: 以数字的顺序进行排序。 (4) u: 去掉输出中的重复行。 (5) t: 如t c,表示以字符c作为分隔符。 (6) k: 如k N,表示按第N个字段排序。 (7) k N1,N2: 表示先按第N1个字段排序,之后再按第N2个字段排序。 前面曾经查看过系统的密码文件/etc/passwd,里面详细列出了用户名、标识、权限代码、家目录等信息,各列数据以: 分隔。 例3.109查看passwd文件的部分内容。 例3.110对passwd文件的第3列数据进行排序显示。 例3.110运行结果表明,以: 作为分隔符,按第3列数据的升序进行了排序,系统默认以字符串的ASCII码作为排序依据。如果想把第3列的数据,如1、100、13、3等,看作数字,则可以在命令中使用n选项把这些值当作数字。 例3.111使用n选项按整数数字排序。 例3.111运行结果表明,n选项可以使命令把数字字符当作整数来进行大小的排序。 2. 管道操作 管道操作符 | 可以连接两个或多个Linux命令,其语法格式如下。 命令1 | 命令2 … 功能说明: 将命令1的标准输出重定向为命令2的标准输入; 标准错误信息(stderr)并不通过管道传播,命令1的错误信息不会传给命令2,命令2的错误信息也不会传给下一个命令等。任何两个命令之间都可以插入管道操作符,管道操作符之前的命令把输出写到标准输出设备上,管道操作符之后的命令再把标准输出设备上的输出当作它的输入。简言之,就是把管道操作符|左边的命令运行结果作为右边命令的输入。 例3.112统计系统上工作的用户有多少。 如果系统上用户很少,直接用who命令就可以看出有几个用户; 但如果系统上用户很多,有几百甚至几千个,那么用管道|让系统统计就会省很多事。 例3.113统计在Linux系统上一共创建了多少用户。 例3.114利用wc命令统计给定目录下的文件个数。 例3.114中,dirpath为目录路径,由read读入。 find命令找出文件,通过管道把这些文件的文件名传输给wc命令,统计出文件名的个数,即给定目录下文件的个数。 如果想列出系统目录/bin下所有文件和目录细节,运行结果可能会显示好几页,需要按PgUp、PgDn或者上下方向键来翻屏。如果把ls命令的输出通过管道送到more命令中,就可以分页查看相关信息了。 例3.115将命令ls的结果输入more命令。 3.5命令行的执行方式 3.5.1命令的顺序执行和并发执行 1. 命令的顺序执行 用分号来分隔两个命令,命令格式如下。 command1;command2;command3;…;commandN 说明: 各命令的执行结果不会影响其他命令的执行。换句话说,每个命令都会执行,但不保证每个命令都执行成功。 例3.116顺序执行命令。 例3.117依次显示目录名和内容。 2. 命令的并发执行 命令并发执行的语法格式如下。 command1& command2& command3& …. commandN& 例3.118几个命令同时执行。 3.5.2命令行中的&&和||操作 1. 命令行中的&&操作 &&: 只有在前面的所有命令都执行成功的情况下才执行后一条命令,这样可以保证所有命令都成功执行,命令语法格式如下。 command1 && command2 && command3 && …&& commandN 例3.119先创建一个目录newdir,然后在该目录中创建两个新文件d1和d2。 例3.119运行结果表明,先用&&命令的执行方式创建了新目录并在新目录中成功新建文件d1,因为命令touch d1 和touch d2是并行执行的,但输入命令时输错了,所以touch d2命令没有执行。第2次输入的命令都正确了,但由于第1次部分命令正确执行了,已经有目录newdir了,第2次希望创建新目录与第1次同名的命令没有成功执行,那么后面的命令就不会被执行,也就不提示新建的文件重名了。 例3.120查看当前目录下是否有sample文件,如果有,则删除该文件,并提示文件已被删除。 当前工作目录下没有sample这个文件,所以第1个命令就没有正确执行,后面的命令也不执行。 2. 命令行中的||操作 ||操作允许持续执行一系列命令,直到有一条命令成功为止,其后的命令将不再被执行。命令语法格式如下。 command1 || command2 || command3 || …|| commandN 例3.121查看当前目录下是否有sample文件,如果有,则后面的命令就不执行; 如果没有,则新建该文件,并提示文件创建成功。 例3.121运行结果表明,命令||和&& 可以组合使用,第1次执行时没有sample文件,所以提示无此文件,然后执行touch 命令创建新文件; 第2次再次执行此命令,因为第1次已经新建了sample文件,所以第2次可以正确执行第1个命令; echo命令是同时执行的,所以也提示新建了文件,但这不是预期的结果。所以,应该把后两个命令连在一起与第1个命令||或操作。再尝试第3次的执行,这才是预期的结果。 3.5.3命令的后台执行及转换 1. 命令的后台执行命令& 在终端或控制台工作时,可能不希望由于运行一个作业而占据屏幕,因为可能还有更重要的事情要做,比如阅读电子邮件。对于密集访问磁盘的进程,用户更希望它能够在每天的非负荷高峰时间段运行(如凌晨),为了使这些进程能够在后台运行,也就是不在终端屏幕上运行,可以让命令在后台运行。命令在后台运行以后,终端上就会显示一个进程号,表示该命令运行的进程编号,用户可以用该进程号来监控该进程,或杀死它。 命令的前台和后台执行命令的语法如下。 (1) command: 在前台执行,就是一般的命令运行形式。 (2) command&: 在后台执行,就是并行执行,在运行结果中会提示[1]3379或[1]done,就表示这个命令在后台的进程号。 适合在后台运行的命令有find、费时的排序及一些Shell脚本。在后台运行作业时要当心,需要用户交互的命令不要放在后台执行,因为在后台运行时看不到运行过程,就不会输入数据,这样机器就会“傻等”直到接收到数据。同时,作业在后台运行一样会将结果输出到屏幕上,干扰用户的工作。如果放在后台运行的作业会产生大量的输出,最好使用如下命令把它的输出重定向到某个文件中,这样,所有标准输出和错误输出都将被重定向到一个叫做out.file 的文件中。 command>out.file2>&1& command>out.file: 将command的输出重定向到out.file文件,即输出内容不打印到屏幕上,而是输出到out.file文件中。 2>&1: 将标准错误信息重定向到标准输出,这里的标准输出已经重定向到了out.file文件,所以将标准错误信息也输出到了out.file文件中。最后一个&是让该命令在后台执行。 试想2>1代表什么?2与>结合代表错误重定向,而1则代表错误重定向到文件1,而不代表标准输出; 如果换成2>&1,&与1结合就代表标准输出了,就变成错误重定向到标准输出。 例3.122在工作目录下查找名字为t1.txt的文件,如果找到,则把结果写入工作目录的file1.pt文件中; 如果有错误,则把错误信息写入/tmp/file1.err文件中。 为了对比,例3.122先在前台执行命令,然后再用后台执行的方式做对比,可以看到在后台运行的命令会在终端上提示命令运行时对应的进程号和运行的命令名。为了对比错误信息,这里故意把命令的名字输入错误。 例3.123查看file1.pt和file1.err命令的运行结果文件。 2. 不中断命令nohup 使用命令&后,作业被提交到后台运行,当前控制台没有被占用,但是一旦把当前控制台关掉(例如,退出账户),作业就会停止运行。nohup命令可以在退出账户之后继续运行相应的进程。nohup就是不挂起(no hang up)的意思。该命令的一般形式如下。 nohup command & 如果使用nohup命令提交作业,那么在默认情况下该作业的所有输出都被重定向到一个名为nohup.out的文件中,可以使用重定向符把结果输出到指定的其他文件,如下示例。 nohup command > myout.file 2>&1 & 使用了nohup之后,还是有可能在当前账户非正常退出或者结束时,命令的执行还是自动结束了,所以在使用nohup让命令在后台运行之后,需要使用exit正常退出当前账户,才能保证命令一直在后台运行。 例3.124不中断的后台作业。 按Ctrl+Z快捷键可以将一个正在前台执行的命令放到后台,并且处于暂停状态。 按Ctrl+C快捷键可以终止前台命令。当一个命令死机或者想提前终止命令的执行时,按Ctrl+C快捷键就可以终止命令的执行。 3. fg和bg命令 fg命令可把后台的进程移到前台执行,bg命令可把前台的进程移到后台执行。 如果前台运行的一个程序需要很长的时间,但是需要干其他事情,就可以按Ctrl+Z快捷键挂起这个程序,然后可以看到如下系统提示(方括号中的是作业号)。 然后可以把程序调度到后台执行,命令如下。bg后面的数字为作业号。 liuhui@liuhui-virtualBox: ~$ bg 1 如果想把它调回到前台运行,可以用如下命令。 liuhui@liuhui-virtualBox: ~$ fg 1 例如,先运行一个耗时较长的命令,然后使用top命令查看服务器负载信息,实时动态刷新显示服务器状态信息,且可以通过交互式命令自定义显示内容。 例3.125查看被终止的命令工作号。 例3.125运行结果界面会显示“[1]+ Stopped top”,1表示是top命令的工作号,然后用bg命令可将top命令转为后台运行。 例3.126将top命令转为后台执行。 因为top命令可以监控服务器的状态信息,转到后台运行后,就看不到运行结果了,但命令一直处于运行状态,如果想使用其他命令,需要按Ctrl+C快捷键退出当前的命令,然后才可以开始一个新的命令。所以在例3.126运行bg命令后按Ctrl+C快捷键退出当前的bg命令,然后再使用fg 1命令把top命令转为前台运行,输入fg 1 后top命令会接着上面的继续运行。 liuhui@liuhui-virtualBox: ~$ fg 1 4. jobs命令 jobs命令可以显示所有挂起的和后台进程的作业号,确定哪一个是当前的进程。在jobs命令的输出里面,当前进程前面有一个+标志,而其他进程通常前面加一个 来标志。 jobs命令语法如下。 jobs [option] [%jobID] 功能说明: 显示所有在jobID中指明的被挂起的和后台进程的状态; 如果没有列表,则显示当前进程的状态。可选参数jobID可以是以%符号开头、以空格符分隔的一串作业号。 常用选项说明如下。 l: 显示该作业的PID。 jobs l: 显示所有任务的PID,jobs命令的状态可以是running、stopped、terminated。 重新输入top命令来监控服务器的状态信息,然后按Ctrl+Z快捷键暂停top命令的执行,按Ctrl+C快捷键退出top命令,接着输入jobs命令查看当前的进程作业号。 例3.127jobs命令的使用。 例3.127运行结果表明top命令被中断了。 3.6文件系统挂载和卸载 3.6.1文件系统挂载 Linux系统中,要访问根目录以外的文件,需要将其“关联”到根目录下的某个目录中,这种关联操作就是“挂载”,这个目录就是“挂载点”,解除此关联关系的过程称为“卸载”。 作为“挂载点”的目录需要满足以下3个要求。 目录事先存在,可以用mkdir命令新建目录。 挂载点目录不可被其他进程使用。 挂载点下原有文件被隐藏。 1. 挂载命令 挂载命令的语法格式如下。 mount [-fnrsvw] [-t vfstype] [-o options] device dir device: 指明要挂载的设备。 dir: 挂载点,执行挂载操作之前必须事先存在。建议使用空目录,因为挂载后原有目录中的内容会被隐藏。 mount命令的常用选项如下。 (1) t: vsftype,指定要挂载的设备上的文件系统类型。 (2) r: readonly,只读挂载。 (3) w: read and write, 读写挂载。 (4) n: 不更新/etc/mtab。 (5) a: 自动挂载所有支持自动挂载的设备,定义在/etc/fstab文件中,且挂载选项中有“自动挂载”功能。 (6) o: 特殊选项。常用的特殊选项如下。 rw/ro:读写/只读,定义文件挂载时是否具有读写权限,默认为rw(读写)。 async/ sync:异步/同步I/O,默认为async(异步)。 atime /noatime: 更新访问时间/不更新访问时间,定义访问分区文件时是否更新文件的访问时间,默认为atime(更新)。 auto/ noauto: 自动/手动,定义执行mount a 命令时,是否自动挂载/etc/fstab文件内容,默认为auto(自动)。 查看内核追踪到的已挂载的所有设备,可用命令cat/proc/mounts。上述选项可多个同时使用,彼此间使用逗号分隔; 默认挂载选项包括rw、suid、dev、exec、auto、nouser及async。 2. 挂载移动硬盘 对Linux系统而言,USB接口的移动硬盘是被当作SCSI设备对待的。插入移动硬盘之前,应先用fdisk l 或 more /proc/partitions命令查看系统硬盘的分区情况。 fdisk命令需要root用户的权限,普通用户无权使用,故应该先用su 将用户切换为root用户,或者使用sudo fdisk l命令短暂使用root权限。 例3.128查看分区情况。 接入移动硬盘后,再用fdisk l 或 more /proc/partitions命令查看系统的硬盘和硬盘分区情况,应该可以发现多了一个SCSI硬盘/dev/sdb1,这就是移动硬盘的逻辑分区。 例3.129查看接入移动硬盘后系统中硬盘的分区情况。 如果接入移动硬盘后无法看到多出来的逻辑分区,则需要先安装USB设备的驱动程序。安装方法是: 在“设置”→“USB设备”中添加USB筛选器,会自动安装USB的驱动程序。安装成功后,在图形界面中可以直接查看U盘内容,在终端用fdisk l 命令就可以看到sdb盘符了,然后使用mount命令就可以在终端使用移动硬盘了,挂载命令执行之前,要确保存在移动硬盘的挂载点,即确保挂载目录存在,如果不存在,则应先创建目录。 例3.130创建挂载目录。 例3.131挂载移动硬盘。 对于例3.131来说,因为安装的是Ubuntu 18.01,并且安装了增强功能,所以在接入移动硬盘时系统自动安装了驱动程序,也就是该移动硬盘可以直接使用,所以在挂载时提示已经挂载成功,挂载的位置在/media/liuhui/0000F6,最后的一长串数字是移动硬盘的卷标。因为事先没有设置该移动硬盘的卷标,所以系统给它分配了一个标识符。命令运行时,系统提示/mnt/usbdb1忙,是因为挂载的移动硬盘容量太大,这里的移动硬盘容量是2.0TB,无法挂载在/mnt目录下,系统将其自动挂载在了/media/liuhui/,如图3.6所示。 图3.6大容量移动硬盘的挂载点 在图形界面中可以直接查看并打开相关文件。 对NTFS格式的磁盘分区应使用mount t ntfs 参数,对FAT32格式的磁盘分区应使用mount t vfat参数。若汉字文件名显示为乱码或不显示,可以使用如下命令。 #mount -t ntfs -o iocharset=cp936 /dev/sdc1 /mnt/usbhd1 #mount -t vfat -o iocharset=cp936 /dev/sdc5 /mnt/usbhd2 3. 挂载U盘 对Linux系统而言,U盘也是被当作SCSI设备对待的,使用方法和移动硬盘完全一样。插入U盘之前和插入之后,应先用fdisk l 或 more /proc/partitions命令查看系统中硬盘的分区情况。 例3.132查看插入U盘后硬盘的分区情况。 由于本系统安装了增强功能,因此在接入U盘时系统自动安装了驱动程序,也就是该U盘可以直接使用。但是Linux系统把U盘当作块文件,不能直接打开,所以还需要把U盘挂载在挂载点上。 例3.133挂载U盘。 挂载后,在终端中,该U盘就是usbsdb1,系统不认识原来的卷标HL。但在图形界面,左侧的Devices中显示的还是原来的卷标HL。在终端可以使用针对文件的各种操作命令,也可以在图形界面直接查看并打开,如图3.7所示。 图3.7图形界面下查看U盘信息 3.6.2文件系统卸载 卸载文件系统可使用umount命令。 例3.134卸载移动硬盘并查看分区情况。 例3.135卸载U盘。 在终端执行umount命令后,即使没有拔出U盘,在终端中也看不到U盘及里面的内容了。在终端使用fdisk和more命令,还可以看到sdb1,即U盘,在图形界面中还可以查看U盘及其内容。 例3.136验证卸载但不拔出U盘的情况。 这是由于U盘还插在USB接口上,fdisk l命令是查看逻辑分区的,因此可以看到sdb1的逻辑分区; 但又由于没有挂载U盘,因此无法看到U盘的内容。 上机实验: Linux文件系统命令的使用 1. 实验目的 (1) 通过对文件的各种操作,掌握Linux环境中文件系统的基本思想,理解一切皆文件的理念。 (2) 通过对mkdir、cp、cd、ls、mv、chmod及rm等文件系统命令的操作,掌握Linux系统中文件系统命令的用法。 (3) 通过对文件系统的挂载使用,理解驱动程序的原理。 2. 实验任务 (1) 文件的新建、复制命令的使用。 (2) 文件内容的搜索命令cat、head、grep、find的使用。 (3) 文件内容的比较命令diff、sdiff、expand的使用。 (4) 文件的输入输出重定向、排序等命令的使用。 (5) 文件系统的挂载命令的使用。 3. 实验环境 装有Windows系统的计算机; 虚拟机安装VirtualBox+ Linux Ubuntu操作系统。 4. 实验题目 任务1: 文件的新建命令touch、复制命令cp、文件类型的查看命令file的使用。 在当前用户的家目录下新建一个文件,文件名是自己的学号,把这个文件复制到一个目录下,查看该文件的类型。 任务2: 文件编辑器gedit、vi、emacs等的使用。 分别使用上述3种文本编辑器,在任务1中新建的文件中输入内容,然后保存,体会3种编辑器的使用不同之处。 任务3: 文件内容的搜索命令cat、head、grep、find的使用。 在任务2中输入内容的文件中搜索相关的关键词。 任务4: 文件内容的比较命令diff、sdiff、expand的使用。 新建一个文件,输入内容,内容与任务2中的内容差别小一点,使用diff、sdiff命令判断两个文件的异同; 再把新建的文件复制一份,比较与原文件之间的异同。 任务5: 文件的归档tar、解压缩gzip等命令的使用。 把当前用户家目录下的文件归档为一个文件,再把当前用户家目录下的文件压缩,查看这两次操作后文件大小的异同。 任务6: 文件系统的挂载命令mount的使用。 把自己的U盘插入计算机,在文件系统中查看U盘; 是否可以在终端中直接查看U盘内容?使用mount命令挂载,然后再查看,有何异同? 5. 实验心得 总结上机中遇到的问题及解决问题过程中的收获、心得体会等。