第5章 Linux文件及目录管理命令基础

第5章 Linux文件及目录管理命令基础

5.1 操作Linux必知必会基础知识

在企业里,绝大多数使用Linux的管理员都是通过命令行来操作Linux的,学会如何通过命令行操作Linux是一个Linux管理员重要的必修课。

5.1.1 Linux命令行组成结构

登录或连接Linux之后,会进入到如下命令行状态:


[[email protected] ~]#

表5-1里针对上述命令行字符的组成给出了各自的含义。

表5-1 命令行字符的含义

提示:第4章中已经简单讲解过命令行的组成知识,若有不清楚的地方,读者可以返回第4章查阅,此处不再赘述。

5.1.2 基本的Linux命令操作语法示例

在操作Linux命令之前,先看下命令操作语法格式图,如图5-1所示。

图5-1 Linux命令操作语法格式图

在Linux系统运维工作中,常用的操作大多都是在命令行下实现的,示例如下:


[[email protected] ~]#  #<==就是在这样的提示符下输入命令。

Linux系统命令操作语法的格式具体如下:


命令 [参数选项]  [文件或路径]
rm   -f          /etc/hosts

说明:

1)中括号[]表示可选,即命令的参数及路径文件是可选的。

2)参数选项表示使用一个命令的不同功能。

3)命令、参数选项、文件或路径两两之间至少要有一个空格。

操作示例:创建一个test文件,然后查看创建结果,最后删除它,再查看删除结果。代码如下:


[[email protected] ~]# touch test.txt #<==创建一个test.txt文件。
[[email protected] ~]# ls #<==查看创建结果。
anaconda-ks.cfg  install.log  install.log.syslog  test.txt #<==结尾带底纹的就是。
[[email protected] ~]# rm -f test.txt #<==删除text.txt。
[[email protected] ~]# ls #<==查看删除结果。
anaconda-ks.cfg  install.log  install.log.syslog #<==test.txt已经没了。

上述代码段中的这一组操作涉及了Linux的三个基本命令:touch(创建文件)、ls(查看目录下的内容)和rm(删除文件或目录)。怎么样?Linux还是很有趣的吧,当你熟练之后你会发现,这样的操作效率远比Windows下高很多,比如批量创建1万个文件的时候。

表5-2通过现实生活中的一个比喻让读者对命令的语法构成印象更加深刻。

表5-2 Linux命令语法格式的形象比喻

5.1.3 Linux与Windows的目录结构对比

大家都熟悉Windows以及Windows的目录结构,图5-2是Linux与Windows的目录结构对比图,该图可以帮助读者快速理解Linux系统的目录结构,更多的目录知识将在第6章详细讲解。

图5-2 Linux与Windows目录结构对比

小结一下,Windows的目录形式为c:\windows\,当然还有d盘、e盘的目录结构,路径分隔符是“\”(撬棍,反斜线),Linux的目录形式为/etc/hosts,路径分割符为“/”(斜线),Linux系统一切目录的起点都是从“/”根开始。

5.2 Linux文件及目录核心命令

操作Linux命令行,最基本的对象就是目录和文件,因此本节开始为大家讲解一些基础且核心的操作Linux的基本命令,读者需要重点掌握。

5.2.1 pwd:显示当前所在位置的信息

【命令星级】  ★★★★★

【功能说明】

pwd命令是“print working directory”中每个单词的首字母缩写,其功能是显示当前工作目录的绝对路径。在实际工作中,我们在命令行操作命令时,经常会在各个目录路径间进行切换,此时可使用pwd命令快速查看当前所在的目录路径。

【语法格式】


pwd  [option]
pwd  [选项] 

说明:

1)注意pwd命令与后面的选项之间至少要有一个空格。

2)通常情况下,执行pwd命令不需要附带任何参数。

【选项说明】

表5-3针对pwd的参数选项进行了说明。

表5-3 pwd命令的参数选项及说明

查看命令帮助时,我们经常会看到“-L,--logical”这样的选项格式,这种写法的意思是“-L”和“--logical”的功能是一样的,在使用选项时,只需要选择一种即可,但不能同时使用,而我们最常用的就是简写的“-L”这种格式。

此外,在表5-3中提到的PWD系统环境变量,可以利用“$”符号输出其值,示例代码如下:


[[email protected] ~]# echo $PWD  #<==echo命令能够输出指定变量,具体用法见echo命令。
/root
[[email protected] ~]# pwd -L     #<==显示逻辑(忽略软链接文件)路径。
/root

也就是说,pwd-L和echo$PWD二者的功能是等价的。

【应用范例】

范例5-1:不带任何选项执行pwd命令。


[[email protected] ~]# pwd             #<==不带任何选项执行pwd命令。
/root                             #<==输出的目录路径为当前用户root的家目录。
[[email protected] ~]# cd /etc/init.d/  #<==进入/etc/init.d/目录,cd命令的具体用法请参
                              见本书5.2.2节cd命令的讲解。
[[email protected] init.d]# pwd
/etc/init.d                     #<==此时用户所在的路径为/etc/init.d目录。

范例5-2:对比使用-L和-P参数(了解即可)。


[[email protected] init.d]# ll /etc/init.d #<==ls命令的具体用法请参见本书ls命令。
lrwxrwxrwx. 1 root root 11 Jan 29 20:29 /etc/init.d -> rc.d/init.d
#<==/etc/init.d是/etc/rc.d/init.d目录的软链接,相当于快捷方式。后面在讲解ln命令时
    (8.2.3节)会讲解此知识。
[[email protected] init.d]# pwd -L     #<==获取环境变量的PWD对应的值,即为echo $PWD的结果。
/etc/init.d
[[email protected] init.d]# echo $PWD  #<==输出环境变量PWD对应的值。
/etc/init.d
[[email protected] init.d]# pwd -P     #<==显示链接对应的源文件的目录路径。
/etc/rc.d/init.d 

范例5-3:在Bash命令行显示当前用户的完整路径。

系统Bash命令行的提示符是由一个叫作PS1的系统环境变量控制的。PS1对应的知识见表5-4。

表5-4 PS1变量对应知识列表

因此,要想查看当前PS1变量的值,可采用如下命令:


[[email protected] ~]# echo $PS1  #<==打印超级管理员对应的PS1值。
[\[email protected]\h \W]\$                #<== @是一个分隔符,与邮箱地址中的@作用类似。

可修改PS1变量对应的值,并让命令行显示全路径:


[[email protected] ~]# PS1='[\[email protected]\h \w]\$ '  #<==将默认的\W改为\w(小写w),此命令仅临时生效。
[[email protected] ~]# cd /etc/sysconfig    #<==切换目录实验。
[[email protected] /etc/sysconfig]#         #<==可以看到此处的路径就是全路径了。

上面的方法只是临时性的,若要让PS1变量永久生效,可采用如下配置方法。

编辑/etc/bashrc文件,找到符合下面内容的一行(大约在第36行),将内容中大写的W改为小写的w,即可让变量永久生效。也就是将:


[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\[email protected]\h \W]\\$ "

改为下面的内容,保存并退出/etc/bashrc文件:


[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\[email protected]\h \w]\\$ "

更漂亮美观的命令行PS1变量设置参数如下:


PS1="[\[\e[34;1m\]\[email protected]\[\e[0m\]\[\e[32;1m\]\H\[\e[0m\]\[\e[31;1m\] \w\[\e[0m\]]\\$"

最后,注销重新登录系统或直接执行source/etc/bashrc使得修改的信息生效,有关Linux终端提示符还有很多有用又好玩的技巧呢!感兴趣的读者可以浏览老男孩博客的相关文章,地址为http://blog.oldboyedu.com/command-line-terminal/。

5.2.2 cd:切换目录

【命令星级】  ★★★★★

【功能说明】

cd命令是“changedirectory”中每个单词的首字母缩写,其功能是从当前工作目录切换到指定的工作目录。

【语法格式】


cd  [option]  [dir] 
cd  [选项]    [目录]

说明:

1)注意cd命令以及后面的选项和目录,每个元素之间都至少要有一个空格。

2)cd命令后面的选项和目录等参数都可以省略。默认情况下,单独执行cd命令,可切换到当前登录用户的家目录(由系统环境变量HOME进行定义)。

3)cd是bash shell的内置命令,查看该命令对应的系统帮助需要使用help cd。

【选项说明】

表5-5针对cd命令的参数选项进行了说明。

表5-5 cd命令的参数选项及说明

对于cd命令,笔者有一些实践经验分享如下。

·在使用cd命令时,如果使用键盘上“Tab”键的自动补齐功能,则可以提高输入速度和准确度。这个“Tab”键的自动补齐功能同样也适用于其他命令。

·需要了解一下路径的概念,比如,相对路径不是从“/”斜线开始的路径,而是从当前目录或指定的目录开始的,例如,data/,mnt/oldboy;绝对路径是从“/”斜线根开始的路径,例如,/data/、/mnt/oldboy。

·当需要切换到当前用户上一次所在的目录时,请使用“cd-”(注意中间的空格);当需要切换到当前用户的家目录时,请使用“cd~”(注意中间的空格);当需要切换到当前目录的上一级目录所在的路径时,请使用“cd..”(注意中间的空格)。

【实践范例】

范例5-4:进入系统/etc目录(cd/etc)。


[[email protected] ~]# pwd
/root #<==在Linux系统中每个用户都有自己的家目录,默认情况下,用户登录系统后会进入自己的
       家目录。root用户的家目录是/root,普通用户的家目录默认是/home/用户名/。
[[email protected] ~]# cd /usr/local/     #<==切换到/usr/local/目录。
[[email protected] local]# pwd
/usr/local                       #<==此时已经进入/usr/local目录了。

范例5-5:切换到当前目录的上一级目录(cd..)。


[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd .. #<==“..”等同于上一级目录名,也可以写成“../”。
[[email protected] usr]# pwd
/usr                       #<==此时切换到了/usr目录。

范例5-6:进入当前目录的父目录的父目录(cd../../)中。


[[email protected] usr]# cd /usr/local/
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd ../../  #<==退到当前目录的上两级目录,即退到“/”目录。
[[email protected] /]# pwd
/

提示:只要目录具有足够多的层次,则可一直这样继续下去“cd../../../..”,直到退到“/”为止。

范例5-7:返回当前用户上一次所在的目录(cd-)。


[[email protected] /]# cd /usr/local/
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd   #<==cd命令不接任何参数时,从环境变量HOME获取路径名,即切换
                                到当前用户的家目录。
[[email protected] ~]# pwd      #<==当前用户的工作路径为/root。
/root
[[email protected] ~]# cd -     #<==执行“cd -”时,cd将从环境变量OLDPWD对应值获取路径名,
/usr/local                #<==即切换到了当前用户上一次的工作路径“/usr/local”。

范例5-8:进入当前用户的家目录(cd~)。


[[email protected] /]# cd /usr/local/
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cd ~       #<==“~”即键盘左上角Esc键下方的波浪符号,其代表家目录。
[[email protected] ~]# pwd
/root                       #<==切换到当前用户的家目录。

提示:执行不带任何参数的cd命令与“cd~”的结果一样。

5.2.3 tree:以树形结构显示目录下的内容

【命令星级】  ★★★★☆

【功能说明】

tree命令的中文意思为“树”,功能是以树形结构列出指定目录下的所有内容,包括所有文件、子目录及子目录里的目录和文件。

【语法格式】


tree  [option]  [directory]
tree  [选项]     [目录] 

说明:

1)注意tree命令以及后面的选项和目录,每个元素之间都至少要有一个空格。

2)若tree命令后不接选项和目录,则默认显示当前所在路径目录的目录结构。

【选项说明】

表5-6针对tree命令的参数选项进行了说明。

表5-6 tree命令的参数选项及说明

【应用范例】

在讲解范例之前,先做一些准备工作,步骤如下。

第一步,安装tree命令。

首先检查系统是否安装了tree命令,如果采用的是最小化安装Linux系统的方式,那么tree命令有可能并没有安装。此时可用yum命令安装tree命令:


[[email protected] ~]# rpm -qa tree        #<==查询tree命令是否安装。
tree-1.5.3-2.el6.x86_64                 #<==如果没有显示就执行下面的命令。
[[email protected] ~]# yum -y install tree #<==安装tree命令的yum命令,本书开头已带读者
                                安装过了。

第二步,调整系统字符集,防止树形结构显示乱码。

在使用树形结构时,很可能会因为字符集而导致出现乱码问题,比如导致树形的树枝部分都是问号,例如,下面的命令可做为临时解决树结构乱码的方法:


[[email protected] ~]# LANG=en_US.UTF-8

这个问题与Linux系统字符集以及我们连接Linux的客户端的字符集都有关联。

范例5-9:不带任何参数执行tree命令。


[[email protected] etc]# cd ~
[[email protected] ~]# tree       #<==显示当前目录结构。
.      #<==“.”以当前目录为起点。
└── anaconda-ks.cfg
0 directories, 1 file

范例5-10:以树形结构显示目录下的所有内容(-a的功能)。


[[email protected] ~]# tree -a #<==带-a参数显示所有文件(包括隐藏文件)。
.
├── anaconda-ks.cfg
├── .bash_history     #<==在Linux系统中,以“.”(点号)开头的文件为隐藏文件,默认不显示。
├── .bash_logout
├── .bash_profile
...省略若干行...
└── .viminfo
0 directories, 9 files

范例5-11:只列出根目录下第一层的目录结构(-L功能)。


[[email protected] ~]# tree -L 1 /      #<==-L参数后接数字,表示查看目录的层数,若不带-L
                       选项则默认显示所有层数。
/
├── bin -> usr/bin
├── boot
├── dev
...省略若干行...
├── media
├── mnt
├── opt
...省略若干行...
└── var
19 directories, 0 files

范例5-12:只显示所有的目录(但不显示文件)。


[[email protected] ~]# tree -d /boot   #<==-d参数表示只显示目录。
/boot
├── efi
│   └── EFI
│       └── centos
├── grub
└── grub2
    ├── fonts
    ├── i386-pc
    └── locale
8 directories
[[email protected] ~]# tree -dL 1 /boot #<==-d参数只显示目录,-L参数表示显示层数,这里是1层。
/boot
├── efi
├── grub
└── grub2
3 directories

范例5-13:使用tree命令区分目录和文件的方法(使用-F和-d参数)。


[[email protected] ~]# tree -L 1 -F /boot/  #<==使用-F参数会在目录后面添加“/”,以方便区分
                                目录。
/boot/
├── config-3.10.0-957.1.3.el7.x86_64
├── config-3.10.0-957.el7.x86_64
├── efi/      #<==结尾带斜线的就是目录。
├── grub/
├── grub2/
├── initramfs-0-rescue-040ea756a4d344249aec0555d4c01569.img
├── initramfs-3.10.0-957.1.3.el7.x86_64.img
...省略若干行...
└── vmlinuz-3.10.0-957.el7.x86_64*
3 directories, 12 files
[[email protected] ~]# tree -L 1 -F /boot/|grep /$   #<==过滤以斜线结尾的所有内容,如果大家
                              暂时还看不懂这个方法,可以等学完grep
                              命令后再回看。
/boot/
├── efi/
├── grub/
├── grub2/
[[email protected] ~]# tree -L 1 -d /boot/   #<==使用-d参数只显示目录树,轻松过滤内容中的目录。
/boot/
|-- efi
|-- grub
`-- lost+found
3 directories

5.2.4 mkdir:创建目录

【命令星级】  ★★★★★

【功能说明】

mkdir命令是由“makedirectories”中每个单词的粗体字母组合而成,其功能是创建目录,默认情况下,如果要创建的目录已经存在,则会提示文件存在,而不会继续创建目录。

【语法格式】


mkdir  [option]  [directory] #<==注意mkdir命令以及后面的选项和目录之间都至少要有一
                                 个空格。
mkdir  [选项]    [目录 ]     #<== mkdir命令可以同时创建多个目录,格式为mkdir dir1
                                 dir2 …

【选项说明】

表5-7针对mkdir命令的参数选项进行了说明。

表5-7 mkdir命令的参数选项及说明

【应用范例】

范例5-14:不使用任何命令参数创建目录的用法示例。

我们先查看下当前目录树的结构,命令如下:


[[email protected] ~] # cd ~
[[email protected] ~] # tree -d 
.               #<==根据结果可以看出当前目录下没有任何目录。
0 directories

开始测试创建目录,并检查,命令如下:


[[email protected] ~]# mkdir data     #<==在当前目录下创建data目录,此处的data是相对路径。
[[email protected] ~]# tree -d
.
└── data     #<==可以看到data目录已经创建。
1 directory
[[email protected] ~]# mkdir data     #<==再次执行创建命令会提示目录已经存在。
mkdir: cannot create directory `data': File exists 

扩展知识:

Windows下的目录路径样式为D:\data\test,而Linux下的路径样式为/data/test,它们的目录顶点和分隔符均不相同。

范例5-15:使用-p参数递归创建目录。

当我们创建多级目录时,如果第一级目录(oldboy)不存在,则创建结果会报错,导致无法成功创建,操作如下:


[[email protected] ~]# mkdir oldboy/test
mkdir: cannot create directory `oldboy/test': No such file or directory 
    #<==提示没有这个文件或目录。

此时,可以指定-p参数递归创建多级目录,命令如下:


[[email protected] ~]# mkdir -p oldboy/test
[[email protected] ~]# tree -d
.
├── data
└── oldboy   #<==同时创建了oldboy目录及oldboy下的子目录test。
    └── test
3 directories

使用mkdir创建多级目录时,建议直接使用-p参数,可以避免出现“No such file or directory”这样没有文件或目录的报错了,且不会影响已存在的目录。

范例5-16:加-v参数显示创建目录的过程。

使用-v参数显示创建目录的详细过程,具体操作命令如下:


[[email protected] ~]# mkdir -pv oldboy2/test
mkdir: created directory `oldboy2'
mkdir: created directory `oldboy2/test'

提示:其实这个-v并无实际用途。

范例5-17:创建目录时可使用-m参数设置目录的默认权限。


[[email protected] ~]# mkdir dir1
[[email protected] ~]# ls -ld dir1                   #<== ls命令的使用方法详见后面的
                                                    5.2.6节ls命令的相关内容。
drwxr-xr-x 2 root root 4096 Nov  5 18:21 dir1  #<==创建该目录的默认权限为755。
[[email protected] ~]# mkdir -m 333 dir2             #<==创建目录时指定333的数字权限。
[[email protected] ~]# ls -ld dir2
d-wx-wx-wx 2 root root 4096 Nov  5 18:21 dir2  #<==可以看到权限已经发生了变化。

提示:有关权限的知识可参考后文讲解的chmod命令。

5.2.5 touch:创建文件或更改文件时间戳

【命令星级】  ★★★★★

【功能说明】

touch命令包含两个功能:一是创建新的空文件;二是改变已有文件的时间戳属性。

【语法格式】


touch  [option]  [file]
touch  [选项]     [文件] 

说明:

1)touch命令以及后面的选项和文件,每个元素之间都至少要有一个空格。

2)注意区分touch和mkdir命令的功能,mkdir命令是创建空目录,而touch是创建空文件。

3)在Linux中,一切皆文件。虽然touch命令不能创建目录,但是可以修改目录的时间戳。

【选项说明】

表5-8针对touch命令的参数选项进行了说明。

表5-8 touch命令的参数选项及说明

【应用范例】

范例5-18:创建文件示例(用于文件事先不存在的情况)。


[[email protected] ~]# mkdir /test          #<==在根下新建一个test目录。
[[email protected] ~]# cd /test/            #<==切换到/test目录。
[[email protected] test]# touch oldboy.txt  #<==创建空文件oldboy.txt。
[[email protected] test]# ls                  #<==可以看到oldboy.txt文件创建成功。
oldboy.txt
[[email protected] test]# touch a.txt b.txt  #<==同时创建多个文件,类似于mkdir创建多个目录。
[[email protected] test]# ls
a.txt  b.txt  oldboy.txt
[[email protected] test]# touch stu{01..05} #<==可以利用大括号“{}”输出的字符序列批量创建
                                          文件。
[[email protected] test]# ls
a.txt  b.txt  oldboy.txt  stu01  stu02  stu03  stu04  stu05

范例5-19:更改文件的时间戳属性。


[[email protected] ~]# stat oldboy.txt #<==stat命令可以查看文件的时间戳属性,具体用法见stat
                                     命令的讲解。
  File: `oldboy.txt'
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 272247      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-07-30 17:37:32.295105308 +0800
Modify: 2015-07-30 17:37:32.295105308 +0800
Change: 2015-07-30 17:37:32.295105308 +0800
#<==说明:文件的时间戳属性分为访问时间、修改时间和状态改变时间。
[[email protected] ~]# touch -a oldboy.txt #<==-a参数可用于更改最后的访问时间。
[[email protected] ~]# stat oldboy.txt
  File: `oldboy.txt'
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 272247      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-07-30 17:48:20.502156890 +0800
Modify: 2015-07-30 17:37:32.295105308 +0800
Change: 2015-07-30 17:48:20.502156890 +0800
[[email protected] ~]# touch -m oldboy.txt  #<==-m参数用于更改最后的修改时间。
[[email protected] ~]# stat oldboy.txt 
  File: `oldboy.txt
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 272247      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-07-30 17:48:20.502156890 +0800
Modify: 2015-07-30 17:48:45.006106223 +0800
Change: 2015-07-30 17:48:45.006106223 +0800

范例5-20:指定时间属性创建/修改文件。

可利用选项-d指定创建文件后的文件修改时间,示例代码如下:


[[email protected] ~]# ls -lh oldboy.txt
-rw-r--r-- 1 root root 0 Oct 23 20:20 oldboy.txt #<==修改前的文件修改时间是10月23日。
[[email protected] ~]# touch -d 20201001 oldboy.txt    #<==指定创建文件后的文件修改时间为2020
                                                     年10月01日。
[[email protected] ~]# ls -lh oldboy.txt
-rw-r--r-- 1 root root 0 Oct  1  2020 oldboy.txt #<==文件修改时间已改为2020年10月01日。

也可利用选项-r,修改oldboy.txt的时间属性,使其与a.txt的时间属性一致,示例代码如下:


[[email protected] ~]# ls -lh a.txt 
-rw-r--r-- 1 root root 0 Oct 23 20:20 a.txt    #<==查看a.txt的修改时间。
[[email protected] ~]# touch -r a.txt oldboy.txt     #<==使用-r参数使得oldboy.txt时间
                                  属性与a.txt一致。
[[email protected] ~]# ls -lh oldboy.txt
-rw-r--r-- 1 root root 0 Oct 23 20:20 oldboy.txt   #<==oldboy.txt文件的修改时间
                                 已与a.txt一致了。

还可以利用选项-t,将文件设置为201512312234.50的时间格式,示例代码如下:


[[email protected] ~]# touch -t 201512312234.50 oldboy.txt
[[email protected] ~]# ls -lh --full-time oldboy.txt
-rw-r--r-- 1 root root 0 2015-12-31 22:34:50.000000000 +0800 oldboy.txt
    #<==查看设置的属性。

上述案例涉及的ls命令的用法详见后面5.2.6节ls的相关内容讲解。

【扩展知识】

这里扩展一点有关时间戳属性的知识。

GNU/Linux的文件共包含3种类型的时间戳:


Access: 2015-07-30 17:48:20.502156890 +0800    #<==文件最后被访问的时间。
Modify: 2015-07-30 17:48:45.006106223 +0800    #<==文件最后被修改的时间。
Change: 2015-07-30 17:48:45.006106223 +0800    #<==文件状态最后被改变的时间。

对应ls命令,查看上述时间戳的选项如下:


mtime: 最后修改时间(ls -lt) #<==修改文件内容,文件的修改时间(modify time)会改变。
ctime: 状态改变时间(ls -lc) #<==修改文件内容、移动文件或改变文件属性等,文件的change
                  时间会改变。
atime: 最后访问时间(ls -lu) #<==查看文件内容时,文件的访问时间(access time)会改变。

5.2.6 ls:显示目录下内容及属性信息的命令

【命令星级】  ★★★★★

【功能说明】

ls命令可以理解为英文单词List的缩写,其功能是列出目录的内容及其内容属性信息(list directory contents)。该命令有点类似于DOS系统下的dir命令,有趣的是Linux下其实也有dir命令,但我们更习惯使用ls。

【语法格式】


ls  [option]  [file]
ls  [选项]     [<文件或目录>] 

说明:

1)ls命令以及后面的选项和文件,每个元素之间都至少要有一个空格。

2)命令后面的选项和目录文件可以省略,表示查看当前路径的文件信息。

【选项说明】

表5-9针对ls命令的参数选项进行了说明。

表5-9 ls命令的参数选项及说明

【应用范例】

在开始范例讲解之前,先做一些准备,顺便整合一下使用前面的命令。准备代码如下:


[[email protected] ~]# mkdir /test  #<==在根“/”下创建一个目录test。
[[email protected] ~]# cd /test/    #<==切换到/test目录下。
[[email protected] test]# touch file1.txt file2.txt file3.txt #<==批量创建若干文件。
[[email protected] test]# mkdir dir1 dir2 dir3 #<==批量创建多个目录,每个目标目录名两端要
                            有空格。
[[email protected] test]# tree                 #<==显示前面创建的文件及目录结构。
.
├── dir1
├── dir2
├── dir3
├── file1.txt
├── file2.txt
└── file3.txt
3 directories, 3 files 

范例5-21:直接执行ls命令,不带任何参数。


[[email protected] test]# ls  #<==不加参数的结果,显示所有文件和目录
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt

范例5-22:使用-a参数显示所有文件,特别是隐藏文件。


[[email protected] test]# touch .file4.txt #<==再创建一个隐藏文件,在Linux系统中以“.”
                         (点号)开头的文件就是隐藏文件。
[[email protected] test]# ls
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt
[[email protected] test]# ls -a
.  ..  dir1  dir2  dir3  file1.txt  file2.txt  file3.txt  .file4.txt
#<==说明:加了-a参数,就会把以“.”(点号)开头的内容显示出来。这里显示的第一个点号,表示当前目录,即test目录本身,而两个点号表示当前目录的上级目录,此处就是代表根目录。有关一个点、两个点的知识,在8.2.3节的ln命令中会有详细讲解。
[[email protected] test]# ls -A #<==列出所有文件,包括隐藏文件,但不包括“.”与“..”这两个目录。
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt  .file4.txt

范例5-23:使用-l参数显示详细信息。


[[email protected] test]# ls -l  #<==此处时间属性列默认显示的是文件的最后一次修改时间。
total 12
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir1
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir2
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir3
-rw-r--r-- 1 root root    0 Oct 25 11:13 file1.txt
-rw-r--r-- 1 root root    0 Oct 25 11:13 file2.txt
-rw-r--r-- 1 root root    0 Oct 25 11:13 file3.txt
#<==说明:这个“-l”参数是最常用的参数,意思是用长格式列出目录下的文件类型、权限,连接数、属主(组)及创建修改时间的信息。这里的每个列的属性含义都需要熟练掌握,后文会详细讨论这些属性信息。

可能有人已经注意到了,创建或修改时间的格式没有年份的信息,那么如何显示时间的全部信息呢?见范例5-24。

范例5-24:显示完整时间属性的参数--time-style=long-iso。


[[email protected] test]# ls -l --time-style=long-iso   #<==以long-iso方式显示时间,
                                 这个命令结果是非常棒的。
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file1.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
#<==提示:这样的时间格式是不是看起来总是让人心情舒畅呢?--time-style的其他可选参数请大家自行测试。

对于上面的命令,说明如下。

1)--time-style包含的可选参数值有:full-iso、long-iso、iso、locale。默认值是locale。

2)在生产场景中经常会遇到同一目录下文件及目录时间的显示不一致的问题,所以需要用ls-l--time-style=long-iso来进行调整,如果觉得参数太多不好记,则可以设置一个别名来进行管理,详见后文的alias命令。

3)值得一提的是,执行ls-l等命令时,默认显示的是文件最后一次修改的时间(如果是新文件就是创建时间)。

4)ls--full-time用于显示完整的时间,等同于ls-l--time-style=full-iso。

既然ls-l输出结果的时间属性列为修改时间,那么能否改成其他的时间呢?例如,显示最后一次文件访问的时间。这当然是可以的,见下文。

范例5-25:执行ls命令,带显示内容的访问时间属性的参数。


[[email protected] test]# stat file1.txt  #<==显示文件的属性及状态信息,stat命令后文会详细
                                        讲解,暂时不用理会。
  File: `file1.txt'
  Size: 0               Blocks: 0         IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 271005     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/   root)   Gid: (    0/    root)
Access: 2015-10-25 11:13:38.875401372 +0800 #<==这里就是文件的访问时间,是我们现在
                                                需要关注的。
Modify: 2015-10-25 11:13:38.875401372 +0800
Change: 2015-10-25 11:13:38.875401372 +0800 
[[email protected] test]# date #<==查看当前的系统时间。
Sun Oct 25 19:44:00 CST 2015 
[[email protected] test]# cat file1.txt   #<==查看文件内容即表示访问文件了,cat命令后面会讲,
                                       暂时不用理会。
[[email protected] test]# stat file1.txt  #<==重新查看文件的访问时间。
  File: `file1.txt'
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 802h/2050d      Inode: 271005      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-10-25 19:44:22.033071250 +0800 #<==我们发现file1.txt的访问时间已经
                                                 发生了变化。
Modify: 2015-10-25 11:13:38.875401372 +0800
Change: 2015-10-25 11:13:38.875401372 +0800
[[email protected] test]# ls -l --time-style=long-iso --time=atime 
    #<==增加--time=atime参数,显示访问时间。
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 19:44 file1.txt #<==文件的时间列确实发生了变化,
                                  是前面的访问时间无疑。
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
[[email protected] test]# ls -l --time-style=long-iso
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file1.txt #<==这里是文件的默认修改
                                                            时间列。
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
#<==通过以上实践,我们可以得出结论了。--time=atime显示的确实是访问时间,而非默认的修改时间。

对于上面的命令,说明如下。

1)与之相关的命令还有ls-l--time-style=long-iso--time=ctime,用于显示文件的改变时间。

2)有关文件时间列及mtime、atime、ctime的知识,前文在介绍touch命令时已经讲解过了。

范例5-26:执行ls命令,带-F参数(有些类似于tree命令的-F)。


[[email protected] test]# ls -F
dir1/  dir2/  dir3/  file1.txt  file2.txt  file3.txt
#<==说明:加了-F之后,我们可以清晰地看到所有目录的结尾都加上了斜线/。这样的功能对于工作有什么用呢?当然有用了,例如,我们要过滤出所有的目录来,那么只需要将带斜线的过滤出来就可以了。
[[email protected] test]# ls -F|grep / #<==过滤目录,grep命令的具体用法见后面grep章节。
dir1/
dir2/
dir3/
[[email protected] test]# ls -F|grep -v /  #<==过滤普通文件。
file1.txt
file2.txt
file3.txt
#<==说明:ls的-F参数是在文件结尾加上文件类型指示符号(*、/、=、@、|,其中的一个)。

范例5-27:使用-d参数只显示目录本身的信息。

有时候我们想查看目录本身的信息,但是若使用“ls目录”命令,就会显示目录里面的内容。示例代码如下:


[[email protected] test]# ls -l dir1  #<==这样根本无法查看dir1目录本身的信息,除非到上级
                      目录中查看。
total 0

如果只是想显示目录本身的信息,那么这个时候参数-d就能派上用场了,示例代码如下:


[[email protected] test]# ls -ld dir1 #<==加-d参数就可以如愿以偿了。
drwxr-xr-x 2 root root 4096 Oct 25 11:13 dir1

范例5-28:使用-R参数递归查看目录。


[[email protected] test]# mkdir dir1/sub1/test -p  #<==递归创建目录的命令。
[[email protected] test]# ls -R dir1               #<==类似于tree但没有tree好用的方法。
dir1:
sub1

dir1/sub1:
test

dir1/sub1/test:


范例5-29:ls命令别名的相关知识及设置ls别名。

可通过如下命令查看ls在系统中的默认别名设置,执行等号前面的内容就会调用后面的命令:


[[email protected] test]# alias|grep ls  #<==alias命令的用法请参见相应的alias章节。
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
#<==提示:什么是别名呢?别名很好理解,就是另外一个名字而已。

例如,显示时间格式的参数太长,这里就可以做个别名,示例代码如下:


[[email protected] test]# alias lst='ls -l --time-style=long-iso' #<==配置命令别名。
[[email protected] test]# alias |grep lst                  #<==检查命令别名是否生效。
alias lst='ls -l --time-style=long-iso'
[[email protected] test]# lst                              #<==执行命令别名,检查效果。
total 12
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir1
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir2
drwxr-xr-x 2 root root 4096 2015-10-25 11:13 dir3
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file1.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file2.txt
-rw-r--r-- 1 root root    0 2015-10-25 11:13 file3.txt
#<==注意:这里的别名是临时生效的,如果希望永久生效则需要将别名放到环境变量的配置里才可以。

范例5-30:查找最近更新过的文件。

在工作中,我们经常需要查看一个包含很多文件的目录,找出最近更新过但不知道具体文件名的文件,这时可以用ls-lrt或者ls-rt这个组合命令,示例代码如下:


[[email protected] test]# touch /etc/test.txt #<==创建一个新文件,假设不知道名字,你如何
                          快速找到它?
[[email protected] test]# ls -lrt /etc/       #<==-t是按时间排序,-r是倒序,即按时间倒序
                          排序。
...省略若干文件行...
-rw-r--r--  1 root root     301 May 22 10:17 mtab
drwxr-xr-x  9 root root    4096 May 22 10:22 sysconfig
-rw-r--r--  1 root root       0 May 22 20:55 test.txt
#<==不用翻屏回查,最后一屏的最后一行就是我们需要查找的文件。如果直接定位文件还可以用如下命令。
[[email protected] test]# ls -lrt /etc|tail -1  #<==tail命令后面会讲。
-rw-r--r--  1 root root       0 May 22 20:55 test.txt

【ls命令输出内容的属性解读】

使用ls命令之后,通常会有类似如下的输出内容:


[[email protected] test]# ls -lhi  #<==-l参数前面已经详细讲解过了,-h参数的作用是将文件的
                    大小以人类可读的方式显示,像下面的4.0K你就能很容易
                    知道文件的大小,-i参数的作用是显示文件的Inode值。
total 12K
97063 drwxr-xr-x 3 root root 4.0K May 22 20:48 dir1
97064 drwxr-xr-x 2 root root 4.0K May 22 11:51 dir2
97065 drwxr-xr-x 2 root root 4.0K May 22 11:51 dir3
97060 -rw-r--r-- 1 root root    0 May 22 11:51 file1.txt
97061 -rw-r--r-- 1 root root    0 May 22 11:51 file2.txt
97062 -rw-r--r-- 1 root root    0 May 22 11:51 file3.txt

上述命令结果中各列的含义如下。

第一列:Inode索引节点编号。

第二列:文件类型及权限(第一个字符为类型,后9个字符为文件权限符号)。

第三列:硬链接个数(详情请参看ln命令(8.2.3节)的讲解)。

第四列:文件或目录所属的用户(属主)。

第五列:文件或目录所属的组。

第六列:文件或目录的大小。

第七、八、九列:文件或目录的修改时间。

第十列:实际的文件名或目录名。

详细解释见图5-3。

【ls输出的文件属性举例说明】

下面以oldboy文件为例说明输出文件的属性细节(具体见表5-10),具体列的内容请参考图5-3。


1736707 -rw-r--r-- 1  root root   35  Oct 28 11:29 oldboy

图5-3 ls命令输出内容的属性解读

表5-10 ls输出的文件属性细节说明

5.2.7 cp:复制文件或目录

【命令星级】  ★★★★★

【功能说明】

cp命令可以理解为英文单词copy的缩写,其功能为复制文件或目录。

【语法格式】


cp  [option]  [source]  [dest]
cp  [选项]    [源文件]  [目标文件]

说明:cp命令以及后面的选项和文件,每个元素之间都至少要有一个空格。

【选项说明】

表5-11针对cp命令的参数选项进行了说明。

表5-11 cp命令的参数选项及说明

【应用范例】

范例5-31:无参数和带参数-a的比较。


[[email protected] test]# pwd
/test 
[[email protected] test]# ll -h #<==查看当前文件的时间属性,读者以自己的系统时间为准。
total 12K
drwxr-xr-x 3 root root 4.0K Nov  3 20:15 dir1
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir2
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir3
-rw-r--r-- 1 root root    0 Nov  3 20:14 file1.txt
-rw-r--r-- 1 root root    0 Nov  3 20:14 file2.txt
-rw-r--r-- 1 root root    0 Nov  3 20:14 file3.txt
[[email protected] test]# cp file1.txt file4.txt    #<==复制file1.txt为file4.txt。
[[email protected] test]# cp -a file1.txt file5.txt #<==使用-a参数复制file1.txt为file5.txt。
[[email protected] test]# ll -h #<==再次查看当前文件的时间属性。
total 12K
drwxr-xr-x 3 root root 4.0K Nov  3 20:15 dir1
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir2
drwxr-xr-x 2 root root 4.0K Nov  3 20:15 dir3
-rw-r--r-- 1 root root    0 Nov  3 20:14 file1.txt  #<==此行是源文件。
-rw-r--r-- 1 root root    0 Nov  3 20:14 file2.txt
-rw-r--r-- 1 root root    0 Nov  3 20:14 file3.txt
-rw-r--r-- 1 root root    0 Nov  3 20:18 file4.txt  #<==此行是未使用任何参数。
-rw-r--r-- 1 root root    0 Nov  3 20:14 file5.txt  #<==此行是使用-a参数进行复制,属性不变。

可以发现,使用-a参数进行复制时,文件的时间属性没有改变,-a参数的功能包含-p参数保持文件的属性功能。

范例5-32:使用-i参数的例子


[[email protected] test]# cp -i file1.txt file5.txt #<==使用-i参数复制文件,会提示是否覆盖文件。
cp: overwrite `file5.txt'? 
[[email protected] test]# cp file1.txt file5.txt    #<==不使用-i参数结果是一样的,为什么呢?
cp: overwrite `file5.txt'?
[[email protected] test]# alias cp                 #<==原因是系统为cp命令默认设置了别名。
alias cp='cp -i'

CentOS系统默认为cp命令设置了别名,即增加了-i的参数。但是在Shell脚本中执行cp命令时,没有-i参数时并不会询问是否覆盖。这是因为命令行和Shell脚本执行时的环境变量不同。不过在脚本中一般使用命令的全路径。

范例5-33:使用-r参数复制目录。


[[email protected] test]# cp dir1 dir2/    #<==复制dir1到dir2,但结果显示跳过目录dir1。
cp: omitting directory `dir1'
[[email protected] test]# cp -r dir1 dir2/ #<==若使用-r参数则复制成功。 
[[email protected] test]# tree dir2        #<==查看复制结果。
dir2
└── dir1
    └── sub1
        └── test
3 directories, 0 files 
#<==提示:使用-a参数也可以达到相同的效果,因为-a参数相当于“dpr”三个参数。

范例5-34:cp覆盖文件不提示是否覆盖的几种方法。

解题思路:屏蔽系统默认的对应的命令别名。

第一种方法,使用命令全路径,示例代码如下:


[[email protected] test]# cp file1.txt file2.txt 
cp: overwrite `file2.txt'? y  #<==提示要输入y以确认覆盖,输入n则为不覆盖。
[[email protected] test]# which cp  #<==查看cp的系统别名。
alias cp='cp -i'
        /bin/cp  #<==CentOS7系统里是/usr/bin/cp,为了兼容CentOS6,将/bin指向了/usr
                    /bin/cp。
[[email protected] test]# /bin/cp file1.txt file2.txt   #<==使用cp命令的绝对路径,即可屏蔽别名。

第二种方法,命令开头使用反斜线\,示例代码如下:


[[email protected] test]# \cp file1.txt file2.txt #<==使用“\”屏蔽系统别名。
[[email protected] test]#  

第三种方法,取消cp的别名,但重启系统失效,示例代码如下:


[[email protected] test]# unalias cp #<==alias设置别名,unalias取消别名,具体用法见对应
                                   章节的内容详解。
[[email protected] test]# cp file1.txt file2.txt 
[[email protected] test]#

第四种为杀鸡取卵的方法,用于开拓思路,不建议采用,示例代码如下:


[[email protected] ~]# cat ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i' #<==编辑这个文件,注释掉本行,重启后生效。“.bashrc”这个文件在开机时会加载。
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

范例5-35:快速备份文件案例。

通常我们备份文件时会使用下面的格式:


[[email protected] ~]# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.ori
#<==观察上面的格式,我们可以发现有一部分路径重复了。因此有了下面的快捷写法,使用了“{}”的
   用法,两种方法是等效的。
[[email protected] ~]# cp /etc/ssh/sshd_config{,.ori}
#<==这种方法的原理是bash对大括号的展开操作,/etc/ssh/sshd_config{,.ori}展开成/etc/
   ssh/sshd_config /etc/ssh/sshd_config.ori再传给cp命令。

5.2.8 mv:移动或重命名文件

【命令星级】  ★★★★★

【功能说明】

mv命令可以理解为英文单词move的缩写,其功能是移动或重命名文件(move/rename files)。

【语法格式】


mv  [option]  [source]  [dest] 
mv  [选项]    [源文件]  [目标文件]

说明:mv命令以及后面的选项和文件,每个元素之间都至少要有一个空格。

【选项说明】

表5-12针对mv命令的参数选项进行了说明。

表5-12 mv命令的参数选项及说明

【应用范例】

范例5-36:对文件改名的例子。


[[email protected] test]# ls
dir1  dir3  file1.txt  file3.txt  file5.txt
dir2  dir4  file2.txt  file4.txt  file6.txt
[[email protected] test]# mv file6.txt file7.txt #<==若file7.txt不存在,则将file6.txt
                                               重命名为file7.txt。
[[email protected] test]# ls
dir1  dir3  file1.txt  file3.txt  file5.txt
dir2  dir4  file2.txt  file4.txt  file7.txt
[[email protected] test]# mv file5.txt file7.txt #<==若file7.txt存在,则将file5.txt覆盖
                                                   file7.txt。
mv: overwrite `file7.txt'? y #<==由于系统默认为mv设置了别名,因此会提示是否覆盖。
[[email protected] test]# alias mv 
alias mv='mv -i' #<==-i参数的功能是若目标文件已经存在,则会询问是否覆盖。
[[email protected] test]# ls
dir1  dir2  dir3  dir4  file1.txt  file2.txt  file3.txt  file4.txt  file7.txt
[[email protected] test]# \mv file4.txt file7.txt #<==若是使用“\”屏蔽系统别名,就不会询问
                                                是否覆盖了。
[[email protected] test]# ls
dir1  dir2  dir3  dir4  file1.txt  file2.txt  file3.txt  file7.txt
[[email protected] test]# 

范例5-37:移动文件的例子。

移动单个文件的示例代码如下:


[[email protected] test]# ls dir1/
sub1
[[email protected] test]# mv file7.txt dir1/ #<==dir1为目录且该目录已存在,则移动file7.txt到
                                           dir1下,若dir1不存在,则重命名为dir1的普通文件。
[[email protected] test]# ls dir1/
file7.txt  sub1 
移动多个文件:
[[email protected] test]# mv file1.txt file2.txt dir1/  #<==第一种方式:多个文件在前,目录在后。
[[email protected] test]# ls dir1/
file1.txt  file2.txt  file7.txt  sub1 
[[email protected] test]# mv dir1/file* . #<==还原试验环境,“file*”匹配所有以file开头的文件

范例5-38:将源和目标调换移动文件到目录(-t参数)。


[[email protected] test]# ls
dir1  dir2  dir3  dir4  file1.txt  file2.txt  file3.txt  file7.txt
[[email protected] test]# mv -t dir1/ file1.txt  file2.txt  file3.txt  file7.txt
    #<==使用-t参数将源和目标进行调换,-t后接目录,最后是要移动的文件。
[[email protected] test]# ls dir1/
file1.txt  file2.txt  file3.txt  file7.txt  sub1

范例5-39:移动目录的例子。


[[email protected] test]# ls
dir1  dir2  dir3  dir4
[[email protected] test]# mv dir1 dir5 #<==目录dir5不存在,将目录dir1改名为dir5
[[email protected] test]# ls
dir2  dir3  dir4  dir5
[[email protected] test]# ls dir5/
file1.txt  file2.txt  file3.txt  file7.txt  sub1 
[[email protected] test]# mv dir2 dir5 #<==若存在目录dir5,则将dir2移动到dir5中
[[email protected] test]# ls dir5/    
dir2  file1.txt  file2.txt  file3.txt  file7.txt  sub1
[[email protected] test]# mv dir3/ dir5/ #<==若在源目录结尾加“/”则不影响结果,但为了规范
                                       和简单起见,建议不加“/”。
[[email protected] test]# ls
dir4  dir5
[[email protected] test]# ls dir5/
dir2  dir3  file1.txt  file2.txt  file3.txt  file7.txt  sub1

5.2.9 rm:删除文件或目录

【命令星级】  ★★★★★

【功能说明】

rm命令可以理解为英文单词remove的缩写,其功能是删除一个或多个文件或目录(remove files or directories)。这是Linux系统里最危险的命令之一,请慎重使用。

【语法格式】


rm  [option]  [file]
rm  [选项]    [<文件或目录>] 

说明:rm命令以及后面的选项和文件目录,每个元素之间都至少要有一个空格。

【选项说明】

表5-13针对rm命令的参数选项进行了说明。

表5-13 rm命令的参数选项及说明

【应用范例】

示例准备代码如下:


[[email protected] ~]# mkdir -p /data/{dir1,dir2,dir3} #<==使用绝对路径创建目录。
[[email protected] ~]# touch /data/{file1.txt,file2.txt,file3.txt}
[[email protected] ~]# tree /data/                                
/data/
├── dir1
├── dir2
├── dir3
├── file1.txt
├── file2.txt
└── file3.txt
3 directories, 3 files
[[email protected] ~]# cd /data/
[[email protected] data]# ls
dir1  dir2  dir3  file1.txt  file2.txt  file3.txt

范例5-40:不带参数删除的实践示例。


[[email protected] data]# rm file3.txt 
rm: remove regular empty file `file3.txt'? n
#<==若输入y就会删除文件,若不想删除则输入n。
[[email protected] data]# alias rm
alias rm='rm -i'  #<==上面会出现提示的原因是rm被设置了系统别名,默认使用了-i参数。
#<==屏蔽别名的方法已经在5.2.7节的cp命令讲解中介绍过了,这里不再赘述。

范例5-41:强制删除的实践示例。


[[email protected] data]# rm -f file3.txt #<==-f参数强制删除,不提示。
[[email protected] data]# ls
dir1  dir2  dir3  file1.txt  file2.txt

提示:使用-f参数强制删除会直接覆盖系统定义的别名。

范例5-42:递归删除的实践示例。


[[email protected] data]# mkdir -p dir1/a/b
[[email protected] data]# tree dir1/
dir1/
└── a
    └── b
2 directories, 0 files 
[[email protected] data]# rm dir1    #<==若无参数就会无法删除目录。
rm: cannot remove `dir1': Is a directory
[[email protected] data]# rm -r dir1 #<==使用-r可以递归删除,但会有确认提示,可以使用-f
                                   进行强制删除。
rm: descend into directory `dir1'? y
rm: descend into directory `dir1/a'? y
rm: remove directory `dir1/a/b'? n
#<==备注:
加上-f参数就不需要一一确认了,例如rm -rf dir1。
若删除的对象不是目录(文件)就不要再使用-r参数了,这样做会很危险,也没有必要。

【有关删除的实践经验分享】

常在河边走,哪有不湿鞋!但如果能遵守下面的要领就可以少湿鞋甚至不湿鞋!

1)用mv替代rm,不要急着删除,而是先移动到回收站“/tmp”。

2)删除前请务必做好备份,最好是异机备份,出现问题随时可还原。

3)如果非要删除,则请用find替代rm,包括通过系统定时任务等清理文件方法。

下面是在生产环境中删除文件或目录的较安全的方法,命令如下:


find . -type f -name "*.txt" -mtime +7|xargs rm –f  #<==与xargs搭配使用,具体用
                                                        法见find命令的详细讲解。
find . -type f -mtime +7 -exec rm {} \;             #<==使用find的exec。

4)如果非要通过rm命令删除,则请先切换目录再删,能不使用通配符的就尽量不用通配符。对文件的删除禁止使用“rm-rf文件名”方法,因为“rm-rf”误删目录时并不会有提示,该操作非常危险。最多使用“rm-f文件名”方法,推荐使用“rm文件名”方法。


[[email protected] /]# cd /oldboy/
[[email protected] oldboy]# rm -f test1 test2

5)如果非要使用通配符,则请按下面的方法进行:


[[email protected] /]# cd /oldboy/
[[email protected] oldboy]# rm -f ./*  #<==加上“./”。
#<==禁止使用rm -fr /oldboy/*,这个命令如果多了空格可能会带来灾难。
[[email protected] /]# rm -fr /oldboy/*
#<==“*”的前面如果不小心多了空格,则会删除当前目录的所有内容,例如下面的命令。
[[email protected] /]# rm -fr /oldboy/ * #<==会把当前目录(根)下面的目录全部删除。

6)额外再补充一点,要慎用“rsync--delete”。

多数情况下,删除数据后是可以恢复的(例如,可通过恢复工具ext3grep来实现),但一定会影响业务,例如,造成停机,或者数据丢失了较长时间,用户访问不了等。未雨绸缪永远比发生了再解决好得多。

更多内容可参考老男孩博客:http://oldboy.blog.51cto.com/2561410/1687300

5.3 Linux文件及目录命令核心知识的试题及详解

本节将要讲解的试题是对读者阅读本章内容后的一个大考察,建议先不要看答案,看能否在Linux命令行下自行解答,然后再与参考答案进行对比,并深入了解题中遇到的相关Linux核心知识和操作规范。

5.3.1 有关cd/pwd/mkdir/ls命令试题

[考题]切换到“/tmp”目录下,查看当前的工作位置,同时创建data1、data2、data3共3个目录。

[参考答案]


[[email protected] ~]# cd /tmp        #<==切换到/tmp目录。
[[email protected] tmp]# pwd          #<==查看当前的工作位置。
/tmp
[[email protected] tmp]# mkdir data1 data2 data3    #<==创建data1、data2、data3共3个目录。
[[email protected] tmp]# ls           #<==操作后查看创建结果,这是个好的习惯。
data1  data2  data3  yum.log  yum_save_tx-2018-03-08-11-04z94H32.yumtx

[重点解析]

创建目录可以一次性到位,且创建多级目录一般要加-p参数,以防止出错,示例代码如下:


[[email protected] tmp]# cd ~          #<==切换到当前用户家目录下。
[[email protected] ~]# rm -fr /tmp/*   #<==删除/tmp/所有内容,“*”代表所有,此命令很危险。
[[email protected] ~]# mkdir /tmp/data{1,2,3} -p    #<==利用大括号批量创建,加-p递归创建,
                                                  {1,2,3}等同于{1..3}。
[[email protected] ~]# ls /tmp         #<==接路径直接查看指定目录下的内容。
data1  data2  data3

5.3.2 有关touch/tree/file命令试题

[考题]接5.3.1节的考题,分别在data1、data2、data3目录下创建3个文件,名字分别为oldboy1、oldboy2、oldboy3,然后查看/tmp目录的整个目录结构情况,最后检查下data1和oldboy1两个对象的属性。

[参考答案]

解答这道考题通常最容易想到的可能是分别在每个目录下处理的笨办法,其实还可以采用另一种快速的方法,注意,此考题依赖5.3.1节考题的结果,解题代码如下:


[[email protected] ~]# touch /tmp/data{1..3}/oldboy{1..3}     #<==一步到位的答案。
[[email protected] ~]# tree /tmp   
-bash: tree: command not found  #<==tree命令没有安装的提示,前文tree命令中已经讲解过了。
[[email protected] ~]# yum install tree -y  #<==安装tree命令,需要系统能够上网才行。
[[email protected] ~]# tree /tmp            #<==tree命令显示目录结构的结果。
/tmp
├── data1
│   ├── oldboy1
│   ├── oldboy2
│   └── oldboy3
├── data2
│   ├── oldboy1
│   ├── oldboy2
│   └── oldboy3
└── data3
    ├── oldboy1
    ├── oldboy2
    └── oldboy3

3 directories, 9 files
[[email protected] ~]# ls -l /tmp #<加-l参数,查看目录下对象的属性。
total 12
drwxr-xr-x. 2 root root 4096 Mar 10 17:11 data1 #<
“d”开头表示data1是目录。
drwxr-xr-x. 2 root root 4096 Mar 10 17:11 data2
drwxr-xr-x. 2 root root 4096 Mar 10 17:11 data3
[[email protected] ~]# ls -l /tmp/data1/
total 0
-rw-r–r--. 1 root root 0 Mar 10 17:11 oldboy1 #<==“-”开头表示oldboy1是文件。
-rw-r–r--. 1 root root 0 Mar 10 17:11 oldboy2
-rw-r–r--. 1 root root 0 Mar 10 17:11 oldboy3


[重点解析]

·大括号{}的使用。

·ls-l命令的使用,以及通过属性开头的符号区分目录和文件知识,“-”表示文件,“d”表示目录。

5.3.3 有关cp命令的试题

[考题]将/etc/hosts文件复制到/tmp/data1下,然后将data1目录复制到/opt下。

[参考答案]


[[email protected] ~]# cp /etc/hosts /tmp/data1/ #<==将/etc/hosts文件复制到/tmp/data1下。
[[email protected] tmp]# ls /tmp/data1
hosts  oldboy1  oldboy2  oldboy3           #<==复制结果。
[[email protected] ~]# cd /tmp
[[email protected] tmp]# cp -r data1 /opt/       #<==将data1目录复制到/opt***意-r。
[[email protected] tmp]# tree /opt
/opt
├── data1    #<==复制结果。
│   ├── hosts
│   ├── oldboy1
│   ├── oldboy2
│   └── oldboy3
└── rh
2 directories, 4 files

[重点解析]

cp功能表示复制文件或目录,但默认不加参数则不能复制目录。如果要复制目录则必须使用-r或者-a参数,以下参数在前文讲解命名时已经讲解过,请读者重点掌握。


-a  相当于-pdr,复制目录也可以使用-a参数。
-r  递归,复制目录,目录及其子孙后代。
-p  复制文件同时保持文件属性不变。

5.3.4 有关mv/rm命令的试题

[考题]将/tmp/data1目录移动到/root目录下,然后删除/opt/data1目录下的hosts文件,最后删除/opt下的data1目录。

[参考答案]


[[email protected] tmp]# cd /tmp    #<==mv是一个很危险的命令,操作前最好进入到对象的上一层次操作。
[[email protected] tmp]# mv data1 /root     #<==将/tmp/data1目录移动到/root目录下。
[[email protected] tmp]# cd /opt/data1      #<==rm是一个很危险的命令,操作前最好进入到对象的
                                          上一层操作。
[[email protected] data1]# rm hosts         #<==删除前请确认。
rm: remove regular file `hosts'? yes  #<==输入yes删除。
[[email protected] data1]# ls
oldboy1  oldboy2  oldboy3             #<==hosts已删。
[[email protected] data1]# rm -f oldboy1    #<==可以加-f直接强制删除,不提示。
[[email protected] data1]# ls
oldboy2  oldboy3                      #<==oldboy1已删。
[[email protected] data1]# cd ..            #<==切换到上一级目录,这点在cd命令章节已讲解过。
[[email protected] opt]# pwd                #<==确认当前所在的位置,防止误删。
/opt
[[email protected] opt]# ls                 #<==确认对象是否存在。
data1  rh
[[email protected] opt]# rm -fr data1       #<==强制删除目录和目录下的所有文件,不提示(危险
                                          命令)。
[[email protected] opt]# ls
rh

[重点解析]

·操作rm、mv命令前,最好对操作的对象先做好备份。

·操作rm、mv命令最好切换到指定的目录,且最好不要在根下直接操作。

·这里的data1与/data1/是没有区别的,都表示目录及目录下的所有内容,其他软件场景可能会有区别。

·删除目录一般使用-rf参数,删除前务必备份,以防误删。

·企业里替代rm以及使用mv的注意事项请参见5.2.9节。

5.4 有关Linux命令的思维

学习Linux命令,仅仅停留在会操作的层面是远远不够的,还要注意操作中可能会遇到的“坑”和解决手段,Linux运维是企业中最关键的岗位,错按一个回车就可以让数据丢失、服务器崩溃,因此,专业规范的操作是优秀的运维人员必须要掌握的基本技术。

5.5 本章相关问题

分别默写出mkdir、ls、cp、rm命令的作用以及常用参数的功能,然后对照本书,检查是否真的记住了。