RHCE9学习指南 第14章 文件系统

在Windows系统中,买了一块新的硬盘加到电脑之后,需要对分区进行格式化才能使用,Linux系统中也是一样,首先我们要先了解一下什么是文件系统。

14.1 了解文件系统

分区很复杂,但是为了好理解不妨先简化介绍。首先来看图14-1,记住这是一个分区。
file
图14-1 了解文件系统
当对一个分区格式化时候分区被分成2部分。
(1)右侧部分被划分成很多小格子,每个小格子称之为block,默认大小为4KB。
(2)左侧部分为inode,用于记录文件属性,每个文件一个inode。
每个block中只能存储一个文件,假设一个文件aa只有1K存放在2号block中,则2号block还剩余3K的空间,但是这3K的空间也不会存储其他数据了。所以,此文件大小为1K,占用的空间为4K,Windows我们应该是经常见到如下情况的,如图14-2所示。
file
图14-2 文件大小和占用空间的区别
如果一个文件的值大于4KB,一个block存放不下,则会占用多个block,例如,某文件大小为9KB,则需要占用3个block。
当要读取某个文件时,如果系统不知道此文件在哪个block中,则要读取所有的block(这个过程称作"遍历"),这样效率是极其低下的。所以,每个文件的属性都有对应的inode条目来记录,例如,图14-1中aa文件由10号inode记录,在inode中记录了aa文件的属性如大小、权限等及此文件占用了哪些block,inode相当于书的目录。当需要读取文件时,在inode中可以快速找到此文件从而快速定位此文件所在的block。
总之,创建文件系统的过程就理解为创建上图小格子的过程,不同的内核所使用的文件系统不一样,例如,Windows常见的文件系统包括fat,NTFS等,Linux中常见的文件系统包括ext3、ext4、xfs等。这些不同的文件系统具有不同的功能,包括所支持单个文件最大能多大,整个文件系统最大能有多大,RHEL8/centos8中默认的文件系统是XFS。

14.2 了解硬链接

前面讲了inode记录的是某文件的属性信息,如图14-3所示。
file
图14-3 了解硬链接
10号inode记录了aa文件的属性,包括aa文件的名称和大小权限等及所在的block,可以在10号inode中给aa文件再起一个名称bb的,如图14-4所示。
file
图14-4 了解硬链接
此时对10号inode来说有用个名称aa和bb来记录2号block中的文件,所以aa和bb对应的是同一个文件,那么aa和bb就是硬链接关系。
练习:先拷贝一个测试文件,命令如下。

[root@server ~]# cp /etc/hosts aa
[root@server ~]#

查看aa的属性,命令如下。

[root@server ~]# ls -lh aa
-rw-r--r--. 1 root root 251 9月  28 11:50 aa
[root@server ~]# 

此处的黑体字1,指的是aa文件只有1个硬链接,即存储在block中的文件只有一个名称aa。下面对aa做硬链接,命令如下。

[root@server ~]# ln aa bb
[root@server ~]#

查看aa和bb的属性,命令如下。

[root@server ~]# ls -lh aa bb
-rw-r--r--. 2 root root 251 9月  28 11:50 aa
-rw-r--r--. 2 root root 251 9月  28 11:50 bb
[root@server ~]#

硬连接数显示为2,说明了存储在block中的那个文件有两个名称aa和bb。aa和bb是在同一个inode上记录的连个名称,通过ls -i可以查看aa和bb分别在哪个inode上记录的,命令如下。

[root@server ~]# ls -i aa ; ls -i bb
34516514 aa
34516514 bb
[root@server ~]#

可以看到,inode值是一样的,即是在同一个inode上用两个名称来记录block中的那个文件。换言之就是aa和bb对应的是同一个文件,修改aa之后会发现bb的内容也做相同的修改,修改bb之后,会发现aa也做了相应的修改。
因为block中的文件现在有两个名称,所以删除掉任意一个之后,block中的数据是不会跟着删除的。所以,删除aa是不会影响bb的,或者删除bb也不会影响aa。但是aa和bb两个同时删除掉,则block中的文件就没有名称了,则此文件会从block中删除。
block中的文件只要还有一个名称,那么这数据就不会删除。如果所有名称都没有了,则此数据会从block中删除。
同一个分区的inode只能记录同一个分区block中的数据,你不能在第二个分区中产生一个inode来记录第一个分区中的文件,所以硬链接不能跨分区。

14.3 创建文件系统

再看看前面已经在/dev/sdb上创建过的分区,命令如下。

[root@server ~]# fdisk -l /dev/sdb 
    ...输出...
设备       启动     起点     末尾     扇区 大小 Id 类型
/dev/sdb1           2048  4196351  4194304   2G 83 Linux
/dev/sdb2        4196352  8390655  4194304   2G 82 Linux swap / Solaris
/dev/sdb4        8390656 41943039 33552384  16G  5 扩展
/dev/sdb5        8392704 12587007  4194304   2G 8e Linux LVM
/dev/sdb6       12589056 16783359  4194304   2G 8e Linux LVM
/dev/sdb7       16785408 20979711  4194304   2G 8e Linux LVM
[root@server ~]#

下面对分区进行格式化,格式化的语法如下。
mkfs -t 文件系统 -选项 /dev/分区
或者
mkfs.文件系统 -选项 /dev/分区
练习:把/dev/sdb1格式化为xfs文件系统,命令如下。

[root@server ~]# mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1           isize=512    agcount=4, agsize=131072 blks
         =                    sectsz=512   attr=2, projid32bit=1
         =                    crc=1        finobt=1, sparse=1, rmapbt=0
         =                    reflink=1
data     =                    bsize=4096   blocks=524288, imaxpct=25
         =                    sunit=0      swidth=0 blks
naming   =version 2           bsize=4096   ascii-ci=0, ftype=1
log      =internal log        bsize=4096   blocks=2560, version=2
         =                    sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                extsz=4096   blocks=0, rtextents=0
[root@server ~]#

从上面bsize=4096可以看到,block的大小默认设置为了4K,如果指定为1K,需要加上选项-b size=1024,命令如下。

[root@server ~]# mkfs.xfs -b size=1024 /dev/sdb1
mkfs.xfs: /dev/sdb1 appears to contain an existing filesystem (xfs).
mkfs.xfs: Use the -f option to force overwrite.
[root@server ~]#

再次格式化时,因为/dev/sdb1已经存在文件系统了,所以再次格式化失败,需要加-f表示强制格式化,命令如下。

[root@server ~]# mkfs.xfs  -f -b size=1024 /dev/sdb1
meta-data=/dev/sdb1          isize=512    agcount=4, agsize=524288 blks
         =                   sectsz=512   attr=2, projid32bit=1
         =                   crc=1        finobt=1, sparse=1, rmapbt=0
         =                   reflink=1
data     =                   bsize=1024   blocks=2097152, imaxpct=25
         =                   sunit=0      swidth=0 blks
naming   =version 2          bsize=4096   ascii-ci=0, ftype=1
log      =internal log       bsize=1024   blocks=10240, version=2
         =                   sectsz=512   sunit=0 blks, lazy-count=1
realtime =none               extsz=4096   blocks=0, rtextents=0
[root@server ~]#

可以看到,现在bsize即block size的大小已经是1024了。这里输出的属性是刚格式化完之后输出的,如果过了一段时间之后想再次查看/dev/sdb1文件系统的属性可以通过xfs_info来进行查看,命令如下。

[root@server ~]# xfs_info /dev/sdb1
meta-data=/dev/sdb1          isize=512    agcount=4, agsize=524288 blks
         =                   sectsz=512   attr=2, projid32bit=1
         =                   crc=1        finobt=1, sparse=1, rmapbt=0
         =                   reflink=1
data     =                   bsize=1024   blocks=2097152, imaxpct=25
         =                   sunit=0      swidth=0 blks
naming   =version 2          bsize=4096   ascii-ci=0, ftype=1
log      =internal log       bsize=1024   blocks=10240, version=2
         =                   sectsz=512   sunit=0 blks, lazy-count=1
realtime =none               extsz=4096   blocks=0, rtextents=0
[root@server ~]#

记住:block size的大小只能在格式化时指定,不可以后期修改。
每个文件系统都会有唯一的一个UUID来记录,查看系统中所有的UUID,可以通过如下命令。

[root@server ~]# blkid
    ...输出...
/dev/sdb1: UUID="69dc14c1-c41b-482b-8654-7344e78e7de1" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="737fabb4-01"
/dev/sdb2: UUID="96b078f8-6ca3-4aac-9af7-b37234b03a6c" TYPE="swap" PARTUUID="737fabb4-02"
/dev/sdb5: PARTUUID="737fabb4-05"
/dev/sdb6: PARTUUID="737fabb4-06"
/dev/sdb7: PARTUUID="737fabb4-07"
    ...输出...
[root@server ~]#

如果想单独查看某个xfs格式文件系统的uuid,可以通过“xfs_admin -u 分区名”来进行查看,命令如下。

[root@server ~]# xfs_admin -u /dev/sdb1
UUID = 69dc14c1-c41b-482b-8654-7344e78e7de1
[root@server ~]#

这里可以看到,/dev/sdb1文件系统的uuid是69dc14c1-c41b-482b-8654-7344e78e7de1。
这个UUID也是可以切换成其他的值的。
通过命令uuidgen手动生成一个新的UUID,命令如下。

[root@server ~]# uuidgen 
d41d59f5-f843-473d-aef4-5062fbf5ae89
[root@server ~]#

把/dev/sdb1的UUID切换成刚新生成的UUID,命令如下。

[root@server ~]# xfs_admin -U d41d59f5-f843-473d-aef4-5062fbf5ae89 /dev/sdb1
Clearing log and setting UUID
writing all SBs
new UUID = d41d59f5-f843-473d-aef4-5062fbf5ae89
[root@server ~]#
再次查看/dev/sdb1的UUID,命令如下。
[root@server ~]# xfs_admin -u /dev/sdb1
UUID = d41d59f5-f843-473d-aef4-5062fbf5ae89
[root@server ~]#

可以看到,现在已经是新的UUID了。

14.4 挂载文件系统

分区格式化好了之后是不可以直接访问的,要想访问此分区必须要把他挂载到某个目录下才行,如同Windows中创建一个分区必须要给它一个盘符或装在某个NTFS文件夹中。
要查看哪些分区已经挂载及分区的使用情况,可以使用df命令,命令如下。

[root@server ~]# df 
文件系统          1K-块    已用     可用 已用% 挂载点
devtmpfs        1870436       0  1870436    0% /dev
tmpfs           1899504       0  1899504    0% /dev/shm
tmpfs           1899504    9864  1889640    1% /run
tmpfs           1899504       0  1899504    0% /sys/fs/cgroup
/dev/sda1      52403200 5241996 47161204   11% /
tmpfs            379900    4640   375260    2% /run/user/1000
tmpfs            379900       0   379900    0% /run/user/0
[root@server ~]#

这里文件系统为tmpfs的是临时文件系统可以忽略不管,上面结果中分区大小都是以K为单位看起来不方便,可以加上-hT选项的,-h会以合适的单位显示,-T会显示文件系统,命令如下。

[root@server ~]# df -hT | grep -v tmpfs
文件系统       类型     容量  已用  可用 已用%        挂载点
/dev/sda1      xfs       50G  5.0G   45G   11%      /
[root@server ~]#

挂载语法的命令如下。
mount -o opt1,opt2,.. /dev/设备 /目录
首先创建一个目录/xx,并拷贝进去几个测试文件,命令如下。

[root@server ~]# mkdir /xx
[root@server ~]# cp /etc/hosts /etc/services /xx
[root@server ~]# ls /xx
hosts  services
[root@server ~]#

下面把/dev/sdb1挂载到/xx中,注意/xx中内容的变化,命令如下。

[root@server ~]# mount /dev/sdb1 /xx
[root@server ~]#

以后访问/xx就是访问/de/sdb1中的内容了,现在查看/xx的内容,命令如下。

[root@server ~]# ls /xx
[root@server ~]#

此时发现/xx中的内容看不到了,原因是如果某个目录挂载了一个分区,则这个目录中原有的内容就会被隐藏,为了好理解,可以参见图14-5。
file
图14-5 没挂载时看到的是/xx中的数据
此时是没有挂载的情况,/xx中有自己的文件,然后把/dev/sdb1挂载到/xx,如图14-6所示。
file
图14-6 挂载之后看到的是/dev/sdb1的数据
例如,有个碗把/xx中原有的内容盖住了,现在看到的是上层碗中的内容,即/dev/sdb1中的内容。只有卸载掉才能再次看到。卸载的命令是umount,用法如下。

umount /挂载点  或者
umount /dev/设备

现在把/dev/sdb1卸载掉,然后查看/xx中的内容,命令如下。

[root@server ~]# umount /dev/sdb1
[root@server ~]# ls /xx
hosts  services
[root@server ~]#

卸载后又能看到/xx里面的内容了,就相当于又把盖在/xx上面的那个“碗”拿掉了,所以能看到了/xx中的内容。
这里需要注意两个问题,第一个问题是假设在/xx没挂载之前,往里面写了一个200GB的文件file,然后又把/dev/sdb1挂载到/xx上,这时的file会被隐藏。有一天发现少了200G的空间,然后到每个目录中找包括/xx,怎么都找不到这200GB。此时得要想到哪些目录是挂载点,这些目录在挂载分区之前,里面是不是存在文件。
第二个问题是,有时卸载时可能无法正常卸载,如同在Windows中卸载U盘时,提示进程正在占用的情况类似,会卸载不掉。先模拟一下这个文件,再次把/dev/sdb1挂载到/xx,命令如下。

[root@server ~]# mount /dev/sdb1 /xx
[root@server ~]#

打开第二个终端执行如下命令,命令如下。

[root@server ~]# cd /xx
[root@server xx]#

这样cd /xx之后,bash进程会一直占用/xx。
再回到第一个终端,卸载/xx,命令如下。

[root@server ~]# umount /xx
umount: /xx: target is busy.
[root@server ~]# umount /dev/sdb1
umount: /xx: target is busy.
[root@server ~]#

发现根本卸载不了,说明/xx现在正在被某个进程占用。那如何查看是哪个进程占用的呢?通过fuser命令,命令如下。

[root@server ~]# fuser -mv /xx
                     用户     进程号 权限   命令
/xx:                 root     kernel mount /xx
                     root      15446 ..c.. bash
[root@server ~]#

这里可以看到,有个进程号为15446的进程正在占用,就是第二个终端中运行的cd命令。
利用kill命令杀死进程号为15446的进程,然后再次卸载,命令如下。

[root@server ~]# kill -9 15446
[root@server ~]# umount /xx
[root@server ~]#

此时可以正常卸载了。这里kill -9 15446的意思是强制杀死进程号为15446的进程,-9表示强制的意思。
挂载时还可以指定一些选项,先看下默认的选项,命令如下。

[root@server ~]# mount /dev/sdb1 /xx
[root@server ~]# mount | grep /xx
/dev/sdb1 on /xx type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
[root@server ~]#

通过执行mount可以看到所有已经挂载了的设备,也可以看到/dev/sdb1的默认挂载选项。这里rw的意思是可读可写,测试往/xx中写如内容,命令如下。

[root@server ~]# ls /xx
[root@server ~]# cp /etc/services /xx
[root@server ~]# ls /xx
services
[root@server ~]#

现在是可以正常写进去的,然后卸载重新以ro选项挂载,命令如下。

[root@server ~]# umount /xx
[root@server ~]# mount -o ro /dev/sdb1 /xx
[root@server ~]# 

查看挂载选项,命令如下。

[root@server ~]# mount | grep /xx
/dev/sdb1 on /xx type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
[root@server ~]#

现在是以ro来挂载的,测试往/xx中写入内容,命令如下。

[root@server ~]# cp /etc/issue /xx
cp: 无法创建普通文件'/xx/issue': 只读文件系统
[root@server ~]#

此时就写不进去了。
如果要想换选项也不用每次都卸载然后再挂载,可以用下面的命令。
mount -o remount,新选项 /挂载点
现在再把/dev/sdb1以rw的方式挂载,命令如下。

[root@server ~]# mount -o remount,rw /xx
[root@server ~]# mount | grep /xx
/dev/sdb1 on /xx type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
[root@server ~]#

然后再次拷贝测试文件进去,命令如下。

[root@server ~]# cp /etc/issue /xx
[root@server ~]# ls /xx
issue  services
[root@server ~]#

可以看到,已经可以正常拷贝过去了。

14.5 设置永久挂载

前面使用mount挂载设备也只是临时生效,当重启系统之后此设备不会自动挂载。如果希望重启之后能自动挂载,需要写入/etc/fstab中,格式如下。

设备      挂载点 文件系统    挂载选项    dump值  fsck值
或者
设备UUID  挂载点 文件系统    挂载选项    dump值  fsck值

最后两列的意义如下。

(1)dump值:意思是能否被dump备份命令作用:dump是一个用来作为备份的命令。通常这个参数的值为0或1
(2)fsck值:是否检验扇区:开机的过程中,系统默认会以fsck检验系统是否为完整(clean)。

这两列值建议写0,不要写其他值。
现在希望/dev/sdb1在重启之后能自动挂载到/xx上,/etc/fstab的写法如下。

[root@server ~]# grep /xx /etc/fstab 
/dev/sdb1   /xx     xfs     defaults        0 0
[root@server ~]#

这样开机就会自动挂载,当然这里也可以写/dev/sdb1的UUID,先获取/dev/sdb1的UUID,命令如下。

[root@server ~]# xfs_admin -u /dev/sdb1
UUID = d41d59f5-f843-473d-aef4-5062fbf5ae89
[root@server ~]#

修改/etc/fstab的内容,命令如下。

[root@server ~]# grep /xx /etc/fstab 
#/dev/sdb1  /xx xfs defaults    0 0
UUID=d41d59f5-f843-473d-aef4-5062fbf5ae89   /xx xfs defaults    0 0
[root@server ~]#

需要注意的是,UUID后面=两边不能有空格,挂载选项使用默认选项,所以写了关键字defaults,记住是defaults不是default,如果要加上其他选项用逗号隔开,例如,以ro方式挂载,修改如下。

[root@server ~]# grep /xx /etc/fstab 
#/dev/sdb1  /xx xfs defaults    0 0
UUID=d41d59f5-f843-473d-aef4-5062fbf5ae89   /xx   xfs   defaults,ro     0 0
[root@server ~]#

选项分隔符逗号两边不要空格。
在写入/etc/fstab之后,如果/dev/sdb1当前没有挂载,执行mount -a可以自动挂载。

14.6 查找文件

有时我们需要在系统中查找一些文件,Windows下有个非常好用的工具Everything,界面如图14-7所示。
file
图14-7 Everything的界面
Everything可以帮助快速找到想要的文件,Linux中也有这样比较方便的工具,这里包括which、locate、find等。
which一般用于查询可执行的路径,例如,要查询vim所在路径,命令如下。

[root@server ~]# which vim
/usr/bin/vim
[root@server ~]#

locate用于查询文件名或路径中含有特定关键字的文件,locate基于数据库文件var/lib/mlocate/mlocate.db进行查询,如果此文件不存在则查询报错,如图14-8所示。
file
图14-8 报错信息
只要使用updatedb创建此文件即可,命令如下。

[root@server ~]# locate aa.zip
/root/aa.zip
[root@server ~]#

这个数据文件默认每天更新一次,所以如果现在创建一个新的文件,命令如下。

[root@server ~]# touch lduanxxx
[root@server ~]# locate lduanxxx
[root@server ~]#

但是此文件在mlocate.db更新之后创建,也就是文件lduanxxx还没出现在此数据库文件中,所以查询不到。此时只要更新一下数据库即可,命令如下。

[root@server ~]# updatedb 
[root@server ~]# locate lduanxxx
/root/lduanxxx
[root@server ~]#

locale命令是用于设置编码的,因为和locate比较像,所以这里提一下。在命令行直接输入locale,命令如下。

[root@server ~]# locale
LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
    ...输出...
LC_ALL=
[root@server ~]#

这里显示了当前系统正在使用的编码为zh_CN.UTF-8,这里显示为中文UTF8编码,命令如下。

[root@server ~]# ls -l /opt/
总用量 0
[root@server ~]#

可以看到,这里会以中文显示,如果想设置为英文UTF8,命令如下。

[root@server ~]# LANG=en_US.UTF-8
[root@server ~]# locale
LANG=en_US.UTF-8
    ...输出...
[root@server ~]# 

再次查看,命令如下。

[root@server ~]# ls -l /opt/
total 0
[root@server ~]#

再次改为zh_CN.UTF-8,命令如下。

[root@server ~]# LANG=zh_CN.UTF-8
[root@server ~]#

这种修改编码的方式只是临时生效,重启之后就不再生效了,如果希望能永久修改,需要修改文件,命令如下。

[root@server ~]# cat /etc/locale.conf 
LANG="zh_CN.UTF-8"
[root@server ~]#

如果只是想执行命令时用指定的编码打开,可以在此命令前加上LANG=编码,命令如下。

[root@server ~]# LANG=en_US.UTF-8 ls -l /opt
total 0
[root@server ~]# ls -l /opt/
总用量 0
[root@server ~]#

LANG=en_US.UTF-8 可以用LANG=C替代。

14.7 find的用法

find是一款功能强大的工具可以基于文件名、创建及修改时间、所有者、大小、权限等进行查询。语法如下。

find 目录  -属性  值
(1)目录:指的是限定在哪个目录下查询,如果不指定则是在当前目录下查询。
(2)属性:指的是基于什么查询,可以根据name,size,user,perm等查询。
(3)值:要依赖于前面的属性,例如,-name lduanxx,这里依据名称进行查询,查询名称为lduanxx的文件。

也可以表示否定的意思,在属性前面加上叹号“!”,语法如下。
find 目录 ! -属性 值
意思是查找属性 不是 这个值的文件。
例如,“! -name lduanxx”,这里依据名称进行查询,查询文件名名称不是lduanxx的文件。
下面的演示都在新创建的目录11下进行查询,命令如下。

[root@server ~]# mkdir 11 ; cd 11
[root@server 11]#

在此目录下创建几个测试文件,命令如下。

[root@server 11]# touch Lduan001 lduan001 
[root@server 11]# dd if=/dev/zero of=file1 bs=1M count=1
    ...输出...
[root@server 11]# dd if=/dev/zero of=file2 bs=1M count=2
    ...输出...
[root@server 11]# dd if=/dev/zero of=file3 bs=1M count=3
    ...输出...
[root@server 11]# dd if=/dev/zero of=file4 bs=1M count=4
    ...输出...
[root@server 11]# dd if=/dev/zero of=file5 bs=1M count=5
    ...输出...
[root@server 11]# 

这里file1到file5的大小如下。

[root@server 11]# du -sh file*
1.0M    file1
2.0M    file2
3.0M    file3
4.0M    file4
5.0M    file5
[root@server 11]#

为了测试方便,按下面命令修改文件的权限,所有者所属组,注意文件名的大小写,命令如下。

[root@server 11]# chown lduan.lduan Lduan001 ; chgrp lduan lduan001 
[root@server 11]# chown 888 file1 ; chgrp 888 file2 ; chown 888.888 file3
[root@server 11]# chmod 326 file1 ; chmod 226 file2 ; chmod 327 file3
[root@server 11]# chmod 441 file4

下面查看所有文件,命令如下。

[root@server 11]# ls -lh 
总用量 15M
--wx-w-rw-. 1       888     root    1.0M    11月 18 12:38 file1
--w--w-rw-. 1       root    888     2.0M    11月 18 12:38 file2
--wx-w-rwx. 1       888     888     3.0M    11月 18 12:38 file3
-r--r----x. 1       root    root    4.0M    11月 18 12:38 file4
-rw-r--r--. 1       root    root    5.0M    11月 18 12:38 file5
-rw-r--r--. 1       root    lduan       0       11月 18 12:37 lduan001
-rw-r--r--. 1       lduan   lduan   0       11月 18 12:37 Lduan001
[root@server 11]#

14.7.1基于名称进行查询

基于名称进行查询,命令如下。

[root@server 11]# find -name lduan001
./lduan001
[root@server 11]#

这里只显示出lduan001并没有显示Lduan001,因为Linux中大小写是完全区分的。如果要忽略大小写,可以使用-iname,命令如下。

[root@server 11]# find -iname lduan001
./Lduan001
./lduan001
[root@server 11]#

这样,不管大写还是小写都能够查询出来。
在使用find时,还是可以使用通配符的,记得要用双引号引起来,命令如下。

[root@server 11]# find -name "file*"
./file1
./file2
./file3
./file4
./file5
[root@server 11]#

这里查询的是文件名以file开头的那些文件。

14.7.2基于文件所有者所属组的查询

根据文件的所有者进行查询,用-user,命令如下。

[root@server 11]# find -user lduan
./Lduan001
[root@server 11]#

这里查询的是所有者为lduan的那些文件。
在查询时,还可以用连接符连接多个查询条件,

(1)-a   表示"和"的关系,两边的条件都要满足
(2)-o   表示"或"的关系,两遍的条件满足一个即可

下面查询所有者为lduan且所属组为也为lduan的文件,命令如下。

[root@server 11]# find -user lduan -a -group lduan
./Lduan001
[root@server 11]#

下面查询所有者为lduan或所属组为lduan的文件,命令如下。

[root@server 11]# find -user lduan -o -group lduan
./Lduan001
./lduan001
[root@server 11]#

还可以根据uid进行查询,用-uid。下面查询文件所有者的uid为1000的那些文件,命令如下。

[root@server 11]# find -uid 1000
./Lduan001
[root@server 11]#

[root@server 11]# id lduan
uid=1000(lduan) gid=1000(lduan) 组=1000(lduan)
[root@server 11]#

因为lduan用户的uid是1000,所以本质上这里查询的就是所有者为lduan的那些文件。
如果文件的所有者或所属组是数字,可以根据-nouser或-nogroup来进行查询。
下面查询没有所有者和没有所属组的文件,命令如下。

[root@server 11]# find -nouser
./file1
./file3
[root@server 11]# find -nogroup
./file2
./file3
[root@server 11]#

14.7.3 基于文件大小的查询

根据文件的大小进行查询,用-size。
查询文件大小等于2M的文件,命令如下。

[root@server 11]# find -size 2M
./file2
[root@server 11]#

查询文件大小大于3M的文件,命令如下。

[root@server 11]# find -size +3M
./file4
./file5
[root@server 11]#

如果大小前面加上+,表示大于,如果加上减号"-",表示小于。

14.7.4 基于文件时间的查询

根据时间进行查询,用-mtime,单位是天,这里天的表示如下。

(1)24小时以内,算是不到1天即一天以内,用 -1表示。
(2)24~48小时,算是1天,用 1表示。
(3)超过48小时算是 超过1天 ,用+1表示。

查询创建时间为1天的文件,命令如下。

[root@server 11]# find -mtime 1
[root@server 11]#

查询创建时间超过1天的文件,命令如下。

[root@server 11]# find -mtime +1
[root@server 11]#

查询创建时间低于1天的文件,命令如下。

[root@server 11]# find -mtime -1
.
./Lduan001
./lduan001
./file1
./file2
./file3
./file4
./file5
[root@server 11]# 

还可以用-mmin,单位是分钟,查找创建时间低于22分钟的文件,命令如下。

[root@server 11]# find -mmin -22
.
./file4
./file5
[root@server 11]#

这里查询多少分钟,大家可以根据自己实际情况替换。

14.7.5基于文件类型的查询

根据文件类型进行查询,用-type。常见的文件类型包括4种。

(1)d:表示目录(文件夹)。
(2)f:表示普通文件。
(3)l:表示软连接(快捷方式)。
(4)b:可用于存储数据的设备文件,如硬盘、光盘等。

在当前目录中找出所有的文件夹,命令如下。

[root@server 11]# find -type d
.
[root@server 11]# 

这里只找到表示当前目录的点“.”。
在当前目录中找到所有的普通文件,命令如下。

[root@server 11]# find -type f
./Lduan001
./lduan001
./file1
./file2
./file3
./file4
./file5
[root@server 11]# 

14.7.6基于文件权限的查询

根据权限进行查询,用-perm。例如,我们要查找权限为326的文件,查询时有3种用法,如图14-9所示。
file
图14-9 基于权限的查询

(1)326:必须完全匹配326,权限不能多也不能少,方块位置的权限都必须要有,圆圈的位置不能有权限。
(2)/326:文件的权限只要配置326中的一个权限即可,如图14-9所示,只要具备方块中的一个权限就可以查询到。
(3)-326:可以比326权限多,但是不能少,如图14-9所示,在方块位置的权限都满足的情况下,圆圈的位置可以多。

通过326查询,命令如下。

[root@server 11]# find -perm 326
./file1
[root@server 11]# 

这里就一个文件的权限完全满足326。
通过/326查询,命令如下。

[root@server 11]# find -perm /326
.
./Lduan001
./lduan001
./file1
./file2
./file3
./file5
[root@server 11]#

这里file4没有查询到,因为file4的权限没有一个上图方块中的权限。
通过-326查询,命令如下。

[root@server 11]# find -perm -326
./file1
./file3
[root@server 11]# 

只要图14-9中方块位置的权限都满足之后,是否有圆圈中权限可以不管,这里找到file1和file3。

14.7.7 find查找含有特殊权限位的文件

查找suid、sgid和粘贴位这些特殊权限位,suid指的是在所有者的位置上有s位,sgid指的是在所属组的位置上有s位,粘贴位指的是other位置有t位。
查询特殊权限位的语法是:

find  /目录  -perm /N000
这里N是4、2、1中某个数字或某几个数字的和,后面3个0表示忽略普通权限。
    N=4:查找含有suid的文件
    N=2:查找含有sgid的文件
    N=1:查找含有粘贴位的文件
    N=6 6=4+2:查找含有suid  或者 含有sgid的文件
    以此类推。

给file1所有者位置添加s位,给file2所属组位置添加s位,给other位置添加t位。

[root@server 11]# chmod u+s file1
[root@server 11]# chmod g+s file2
[root@server 11]# chmod o+t file3
[root@server 11]#

查看含有suid的文件。

[root@server 11]# find -perm /4000
./file1
[root@server 11]#

这里只有file1满足条件。
查找含有sgid的文件。

[root@server 11]# find -perm /2000
./file2
[root@server 11]#

只有file2满足条件。
查找含有粘贴位的文件。

[root@server 11]# find -perm /1000
./file3
[root@server 11]# 

只有file3满足条件。
查找含有特殊权限位的文件,不管是suid、sgid还是粘贴位。

[root@server 11]# find -perm /7000
./file1
./file2
./file3
[root@server 11]#

file1、file2、file3都满足。

14.7.8 find组合查询

find可以支持组合查询,语法如下。
find /目录 \( 条件1 -o 条件2 \) -a \( 条件3 -o 条件4 \)
注意:这里"("后要有空格, ")"前也要有空格。
这里( 条件1 -o 条件2 )是一个整体,条件1和条件2是"或"的关系,只要有一个条件即可。( 条件3 -o 条件4 )也是一个整体,条件3和条件4也是"或"的关系,只要满足一个条件即可。
这两个整体之间又是"和"的关系,这两个整体都要满足才行。

看下面的例子,在当前目录中找出文件大于或等于3M,且没有所有者或没有所属组的文件。
分析:
第一个条件是,文件的大小要大于3M或小于3M,这两者是或的关系,应该写作-size 3M -o -size +3M,这是一个整体。
第二个条件是,没有所有者或没有所属组,这两个也是或的关系,应该写作-nouser -o -nogroup,这也是一个整体。
这两个整体之间是“和”的关系,即这两个整体都要满足,所以最终写成如下样子。

[root@server 11]# find \( -size 3M -o -size +3M \) -a \( -nouser -o -nogroup \)  
./file3
[root@server 11]#

这里找到只有file3是满足条件的,查看这些文件的属性。

[root@server 11]# ls -lh 
总用量 15M
--ws-w-rw-. 1       888     root    1.0M    11月 18 12:38 file1
--w--wSrw-. 1       root    888     2.0M    11月 18 12:38 file2
--wx-w-rwt. 1       888     888     3.0M    11月 18 12:38 file3
-r--r----x. 1       root    root    4.0M    11月 18 12:38 file4
-rw-r--r--. 1       root    root    5.0M    11月 18 12:38 file5
-rw-r--r--. 1       root    lduan       0       11月 18 12:37 lduan001
-rw-r--r--. 1       lduan   lduan   0       11月 18 12:37 Lduan001
[root@server 11]#

14.7.9 排除某个目录

当在某个目录里查询时,它会在此目录及所有子目录中查询,想排除某个目录的查询的语法如下。
find path1 \( -path path1/path2 -o -path path1/path3 \) -prune -o 条件 -print
这里的意思是在path1中查询,但是要排除path1下的path2和path3,这里-prune的意思是排除出现他前面的目录,这里最后的"-print"是需要加上去的。

例如,我们在根'/'下查找没有所有者或没有所属组,且文件大小大于1M的文件,命令如下。

[root@server 11]# find  /  \( -nouser -o -nogroup \) -a -size +1M 
find: ‘/proc/39091/task/39091/fd/5’: 没有那个文件或目录
find: ‘/proc/39091/task/39091/fdinfo/5’: 没有那个文件或目录
find: ‘/proc/39091/fd/9’: 没有那个文件或目录
find: ‘/proc/39091/fdinfo/9’: 没有那个文件或目录
find: ‘/run/user/1000/gvfs’: 权限不够
/root/11/file2
/root/11/file3
[root@server 11]#

这里可以看到,它也会到/proc和/run目录中查询,如果想排除“/proc”和“/run”呢?

[root@server 11]# find / \(  -path /proc -o -path  /run  \) -prune  -o \(  \( -nouser -o -nogroup \) -a -size +1M  \)  -print
/root/11/file2
/root/11/file3
[root@server 11]#

这里找到了/root/11/file2和/root/11/file3是满足条件的,没有到/run和/proc中去查询。

14.7.10 对查询结果操作

对find找出来的文件进行相关操作。例如,找到file*开头的文件并删除,命令如下。

[root@server 11]# find -name "file*" -exec rm -rf  {} \;
[root@server 11]#

这里find -name "file*"的意思是找到file开头的文件,通过-exec作为连接符,然后后面跟着操作这些文件的命令。这里是rm命令,{}表示find找到的那些文件,最后"\;"是固定的格式。
再次查看当前目录中的文件,命令如下。

[root@server 11]# ls
lduan001  Lduan001
[root@server 11]#

可以看到,所有file开头的文件都已经被删除了。

作业

练习题在server2上完成。
作业1:在上一章中,已经对/dev/sdb创建了几个分区,请把/dev/sdb1格式化为xfs文件系统。

作业2:创建目录/data,并把/dev/sdb1挂载到/data目录,并设置永久生效。

作业3:在/下(排除/proc和/run)查找含有特殊权限位(含有suid或sgid或粘贴位)且小于1M的文件或目录,并以ls -ld显示此文件/目录的属性信息。

相关新闻

发表回复

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

                                                                                                                                    RHCE9学习指南连载,点击阅读