linux系统中查找文件有两个工具 : locatefind。查找文件有点类似于使用英文词典查单词。查找文件有点类似于使用英文词典查单吃。比如当你想要找一个词的时候,你可以使用字典前面的目录索引,先在目录索引中找到具体单词所在的页码位置,然后跟进目录信息,直接找到对应此所在的位置,或者可以从字典的第一页开始,一页一页的逐个匹配,指导找到对应的内容。locate命令查找文件的方式就是基于第一种方式,find命令类似于第二种方式。

1. locate

这个命令默认没有在centos7中安装, 安装包的名称是mlocate-0.26-8.el7.x86_64

locate命令是对文件索引数据库中的内容进行搜索的。如果是linux系统刚刚装好,马上执行locate命令,比如:locate /bin/ls,执行效果如下:

[root@localhost ~]# locate  /bin/ls
locate: can not stat () `/var/lib/mlocate/mlocate.db': No such file or directory

如上例所示:执行命令后并没有显示出ls文件所在的位置,反而是报错,提示没有mlocate.db文件,去报错指定的目录/var/lib/mlocate下查找mlocate.db确实不存在。报这个错是因为locate命令是跟进目录索引数据库文件创建目录索引数据库文件mlocate.db来查找文件的。当初始安装的情况下,默认并没有根据当前文件系统中的文件创建目录索引数据库文件,因此locate命令无法使用。

既然locate是要基于mlocate.db这个目录索引文件查找文件的,有两种方式生成该文件:第一,等一段时间后,系统会自动生成此文件;第二,利用updatedb命令实现。使用updatedb,索引构建过程需要遍历整个根文件系统极消耗资源。

工作特点

  • 查找速度快

  • 模糊查找

  • 非实时查找

  • 搜索的是文件的全路径,不仅仅是文件名

  • 可能只搜索用户具备读取和执行权限的目录

示例

[root@localhost ~]# updatedb
[root@localhost ~]# ll /var/lib/mlocate/
total 2888
-rw-r-----. 1 root slocate 2954527 Aug 25 03:04 mlocate.db
[root@localhost ~]# locate /bin/ls
/usr/bin/ls
/usr/bin/lsattr
/usr/bin/lsblk
/usr/bin/lscpu
/usr/bin/lsgpio
/usr/bin/lsiio
/usr/bin/lsinitrd
/usr/bin/lsipc
/usr/bin/lslocks
​

使用updatedb命令后,系统中创建了mlocate.db文件。然后我们使用locate /bin/ls去查找ls命令所在的位置,发现查找的结果中只要文件绝对路径中包含/bin/ls字符的所有内容都被查找出来了。另外updatedb命令对应的有一个相当的配置文件/etc/updatedb.conf,此文件中里面定于了创建mlocate.db目录索引的工作范围

[root@localhost ~]# cat /etc/updatedb.conf 
PRUNE_BIND_MOUNTS = "yes"
PRUNEFS = "9p afs anon_inodefs auto autofs bdev binfmt_misc cgroup cifs coda configfs cpuset debugfs devpts ecryptfs exofs fuse fuse.sshfs fusectl gfs gfs2 gpfs hugetlbfs inotifyfs iso9660 jffs2 lustre mqueue ncpfs nfs nfs4 nfsd pipefs proc ramfs rootfs rpc_pipefs securityfs selinuxfs sfs sockfs sysfs tmpfs ubifs udf usbfs ceph fuse.ceph"
PRUNENAMES = ".git .hg .svn .bzr .arch-ids {arch} CVS"
PRUNEPATHS = "/afs /media /mnt /net /sfs /tmp /udev /var/cache/ccache /var/lib/yum/yumdb /var/lib/dnf/yumdb /var/spool/cups /var/spool/squid /var/tmp /var/lib/ceph"
​
  • PRUNE_BIND_MOUNTS = "yes",代表目录索引不扫描挂载点下的内容。

  • PRUNEFS : 代表此类文件系统不会被目录索引扫描。

  • PRUNENAMES : 代表此类文件名后缀的文件不会被目录索引扫描

  • PRUNEPATHS : 代表此类路径下的内容不会被目录索引扫描

除了手动使用updatedb命令更新目录索引外,mlocate默认安装后,有一个周期计划任务,会每天更新一下mlocate.db文件,这个计划任务文件为:/etc/cron.daily/mlocate.cron

locate命令语法格式 : locate [OPTION]... PATTERN...

常用选项说明

选项

说明

-i

不区分大小写的搜索

-n #,--limit,-l

只列表前#个匹配项目

-r

使用基于正则表达式

--regex

使用扩展正则表达式

-b

只匹配基名,默认匹配全路径

-c

显示匹配文件的数量

默认情况下locate命令会根据绝对路径查找匹配文件,但是有的时候我们只是想使用基名来查找内容,这时就可以使用-b选项了,只匹配文件的基名即basename

[root@localhost ~]# locate sysconfig
/etc/sysconfig
/etc/sysconfig/anaconda
/etc/sysconfig/atd
/etc/sysconfig/cbq
/etc/sysconfig/chronyd
/etc/sysconfig/console
/etc/sysconfig/cpupower
/etc/sysconfig/crond
...
​
​
[root@localhost ~]# locate -b sysconfig
/etc/sysconfig
/usr/lib/python3.6/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg
/usr/lib/python3.6/site-packages/pip/_vendor/distlib/_backport/sysconfig.py
/usr/lib/python3.6/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-36.opt-1.pyc
/usr/lib/python3.6/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-36.pyc
/usr/lib64/python3.6/_sysconfigdata_dm_linux_x86_64-linux-gnu.py
/usr/lib64/python3.6/_sysconfigdata_m_linux_x86_64-linux-gnu.py
/usr/lib64/python3.6/sysconfig.py
​

默认情况下,locate命令会将查找到的文件的绝对路径打印到屏幕上,有的时候我们只是想查看匹配到的数据而不是内容,这时使用-c选项即可

[root@localhost ~]# locate ls | wc -l
3781
[root@localhost ~]# locate -c ls
3781

当一般的名称格式不能够满足查找需要时,可以使用-r选项支持正则表达式

[root@localhost ~]# locate -l 3 -r "\.conf$"
/boot/loader/entries/098454bbaa8b420eb5e0552deeb8a2fb-0-rescue.conf
/boot/loader/entries/098454bbaa8b420eb5e0552deeb8a2fb-4.18.0-193.el8.x86_64.conf
/etc/asound.conf

locate命令只能找到mlocate.db文件中收录的文件,如果是一个新创建的文件,那么使用locate是无法查找到的。所以locate适合搜索相对静态不常变化的文件。

2. find

相对于locate基于目录索引查找文件,find则会根据查找条件在指定路径直接实现递归查找文件,find不依赖目录索引,但是当查找目录范围过大、文件过多时效率不高。

语法格式 : find 查找选项 [查找路径范围] 表达式 [处理动作]

说明: 查找路径范围默认为当前路径

2.1 查找表达式

  • 搜索层级

    • -maxdepth level : 最大搜索目录深度,指定目录为第1级

    • -mindepth level : 最小搜索目录深度

  • 根据文件名和inode查找 :

    • -name "文件名称" : 支持使用glob,*, ?, [], [^]

    • -iname "文件名称" : 不区分字母大小写

    • -inum n : 按inode号查找

    • -samefile name : 相同inode号的文件

    • -links n : 链接数为n的文件

    • -regex "PATTERN" : 以PATTERN匹配整个文件路径字 符串,而不仅仅是文件名称

  • 根据属主、属组查找 :

    • -user USERNAME : 查找属主为指定用户(UID)的文件

    • -group GRPNAME : 查找属组为指定组(GID)的文件

    • -uid UserID : 查找属主为指定的UID号的文件

    • -gid GroupID : 查找属组为指定的GID号的文件

    • -nouser : 查找没有属主的文件

    • -nogroup : 查找没有属组的文件

  • 根据文件类型查找 :

    -type TYPE:

    • f: 普通文件

    • d: 目录文件

    • l: 符号链接文件

    • s : 套接字文件

    • b: 块设备文件

    • c: 字符设备文件

    • p: 管道文件

  • 组合条件 :

    • -a : 与

    • -o : 或

    • -not, ! : 非

    德·摩根定律 :

    • (非 A) 或 (非 B) = 非(A 且 B)

      !A -o !B = !(A -a B)

    • (非 A) 且 (非 B) = 非(A 或 B)

      !A -o !B = !(A -a B)

  • 根据文件大小来查找 :

    • -size [+|-]#UNIT,常用单位 : k, M, Gc(byte)

    • #UNIT : (#-1, #];如 : 6k,表示(5k,6k]

    • -#UNIT : [0,#-1];如 : -6k,表示[0,5k]

    • +#UNIT : (#,∞);如 : +6k,表示(6k,∞)

  • 根据时间戳 :

    • 以“天”为单位;

      • -atime [+|-]#,

        • # : [#,#+1)

        • +# : [#+1,∞]

        • -# : [0,#)

      • -mtime

      • -ctime

    • 以“分钟”为单位 :

      • -amin

      • -mmin

      • -cmin

  • 根据权限查找 :

    • -perm [/|-]MODE

      • MODE : 精确权限匹配

      • /MODE : 任何一类(u,g,o)对象的权限中只要能一位匹配 即可,或关系,+centos7开始淘汰

      • -MODE : 每一类对象都必须同时拥有指定权限,与关系。这个选项中 0 表示不关注

    • find -perm 755 : 会匹配权限模式恰好是755的文件

    • 只要当任意人有写权限时,find -perm +222就会匹配

    • 只有当每个人都有写权限时,find -perm -222才会匹配

    • 只有当其它人(other)有写权限时,find -perm -002才 会匹配

示例

find -name snow.png 
find -iname snow.png 
find / -name  “*.txt” 
find /var –name “*log*” 
find  -user joe  -group joe 
find -user joe -not -group joe 
find -user joe -o -user jane 
find -not  \(  -user joe -o -user jane  \) 
find / -user joe -o -uid 500
​
​
找出/tmp目录下,属主不是root,且文件名不以f开头的文件
find /tmp \( -not -user root -a -not -name 'f*' \) -ls
find /tmp -not \( -user root -o -name 'f*' \)  –ls 
​
查找/etc/下,除/etc/sane.d目录的其它所有.conf后缀的文件   
find /etc -path ‘/etc/sane.d’ -a -prune    -o -name “*.conf” 
​
查找/etc/下,除/etc/sane.d和/etc/fonts两个目录的其它所 有.conf后缀的文件  
find /etc \(–path ‘/etc/sane.d’ –o –path ’/etc/fonts’ \)   -a -prune –o -name “*.conf” 
​

2.2 处理动作

  • -print : 默认的处理动作,显示至屏幕

  • -print0 : 在find的每一个结果之后加一个NULL字符 , 而不是默认加一个换行符。find的默认在每一个结果后加一个\n , 所以输出结果是一行一行的。当使用了-print0之后 , 就变成一行了。

    选择NULL做分隔符 , 是因为一般编程语言把NULL作为字符串结束的标志 , 所以文件名不可能以NULL结尾 , 这样确保万无一失。

  • -ls : 类似于对查找到的文件执行ls -l命令

  • -delete : 删除查找到的文件

  • fls file : 查找到的所有文件的长格式信息保存至指定文件中

  • ok COMMAND {} \; 对查找到的每个文件执行由COMMAND 指定的命令,对于每个文件执行命令之前,都会交互式要求用 户确认

  • -exec COMMAND {} \; 对查找到的每个文件执行由 COMMAND指定的命令

  • {}: 用于引用查找到的文件名称自身

  • find传递查找到的文件至后面指定的命令时,查找到所有符合 条件的文件一次性传递给后面的命令

find  -name  “*.conf”  -exec  cp {}  {}.orig  \; 
备份配置文件,添加.orig这个扩展名
​
find /tmp -ctime +3 -user joe -ok rm {} \; 
提示删除存在时间超过3天以上的joe的临时文件 
​
find ~ -perm -002  -exec chmod o-w {} \; 
在你的主目录中寻找可被其它用户写入的文件 
​
find /data –type  f -perm 644  -name “*.sh” –exec chmod 755 {} \; 
find  /home –type d -ls 
 
find . -name "*.txt" -print0 | xargs -0 rm


参考链接

find -print0和xargs -0原理及用法 - liuyihua1992 - 博客园 (cnblogs.com)


熊熊