文件查找

  • 非实时查找(数据库查找):locate
  • 实时查找:find

1 locate

  • locate查询系统上预建的文件索引数据库/var/lib/mlocate/mlocate.db
  • 索引的构建是在系统较为空闲时自动进行(周期性任务),执行updatedb可以更新数据库
  • 索引构建过程中需要遍历整个根文件系统,很消耗资源
  • locate和updatedb命令来自于mlocate包

工作特点:

  • 查找速度快
  • 模糊查找
  • 非实时查找
  • 搜索的是文件的全路径,不仅仅是文件名
  • 可能只搜索用户具备读取和执行的目录

格式:

locate [OPTION]... [PATTERN]...

常用选项:

  • -i   不区分大小写搜索
  • -n N   只列举前N个匹配项目
  • -r   使用基本正则表达式
# 搜索名称或路径中包含“conf”的文件
locate conf
# 使用Regex来搜索以“.conf”结尾的文件
locate -r '.conf$'

locatedb创建数据库

[root@centos8 ~]# yum install mlocate -y
[root@centos8 ~]# locate conf
locate: can not stat () `/var/lib/mlocate/mlocate.db': No such file or directory
[root@centos8 ~]# ll /var/lib/mlocate/mlocate.db
ls: cannot access '/var/lib/mlocate/mlocate.db': No such file or directory
[root@centos8 ~]# updatedb
[root@centos8 ~]# ll /var/lib/mlocate/mlocate.db
-rw-r-----. 1 root slocate 921649 Mar 22 11:20 /var/lib/mlocate/mlocate.db
[root@centos8 ~]# locate -n3 conf
/boot/config-4.18.0-147.el8.x86_64
/boot/grub2/i386-pc/configfile.mod
/boot/loader/entries/aba3a1f3bf4b4616bde0da11b7197aa5-0-rescue.conf

文件新创建和删除,无法马上更新locate数据库

[root@centos8 ~]# touch test.log
[root@centos8 ~]# locate test.log 
[root@centos8 ~]# updatedb
[root@centos8 ~]# locate test.log 
/root/test.log  
[root@centos8 ~]# touch test1.log
[root@centos8 ~]# locate test1.log 
[root@centos8 ~]# updatedb 
[root@centos8 ~]# locate test1.log  
/root/test1.log
[root@centos8 ~]# rm -f test1.log 
[root@centos8 ~]# locate test1.log 
/root/test1.log
[root@centos8 ~]# updatedb 
[root@centos8 ~]# locate test1.log

查找以.CONF为结尾的前十个文件并忽略大小写

[root@centos8 ~]# locate -n10 -ir '.CONF$'
/boot/loader/entries/aba3a1f3bf4b4616bde0da11b7197aa5-0-rescue.conf
/boot/loader/entries/aba3a1f3bf4b4616bde0da11b7197aa5-4.18.0-147.el8.x86_64.conf
/etc/dracut.conf
/etc/fuse.conf
/etc/host.conf
/etc/idmapd.conf
/etc/kdump.conf
/etc/krb5.conf
/etc/ld.so.conf
/etc/libaudit.conf

2 find

find是实时查找工具,通过遍历指定路径完成文件查找

工作特点:

  • 查找速度慢
  • 精确查找
  • 实时查找
  • 查找条件丰富
  • 可能只搜索用户具备读取和执行权限的目录

格式:

find [OPTION]... [查找路径] [查找条件] [处理动作]
  • 查找路径:制定具体的目标路径;默认为当前目录
  • 查找条件:指定的查找标准,可以文件名、大小、类型、权限等标准进行;默认为找出指定路径下所有文件
  • 处理动作:对符号条件的文件做操作,默认输出至屏幕
2.1 指定搜索目录层级
  • -maxdepth level  最大搜索目录深度,指定目录下的文件为第1级
  • -mindepth level   最小搜索目录深度
[root@centos8 ~]# find /etc/ -maxdepth 2 -mindepth 2
/etc/dnf/modules.d
/etc/dnf/vars
/etc/dnf/aliases.d
/etc/dnf/dnf.conf
/etc/dnf/modules.defaults.d
/etc/dnf/plugins
/etc/dnf/protected.d
2.2 对每个目录先处理目录内的文件,再处理目录本身
-depth -d

例:

[root@centos8 ~]# tree test
test
├── f1.sh
└── test1
    └── f1.txt

1 directory, 2 files
[root@centos8 ~]# find /root/test/
/root/test/
/root/test/test1
/root/test/test1/f1.txt
/root/test/f1.sh
[root@centos8 ~]# find /root/test/ -depth
/root/test/test1/f1.txt
/root/test/test1
/root/test/f1.sh
/root/test/
2.3 根据文件名和inode查找
  • -name "FileName" 支持使用glob,如:*.?.[].[^],通配符要加双引号引起来
  • -iname "FileName" 不区分字符大小写
  • -inum n      按inode查找
  • -samefile name  相同inode号的文件
  • -links n       链接数为n的文件
  • -regex "PATTERN" 以PATTERN匹配整个文件路径,而非文件名称
[root@centos8 ~]# find -name f1.txt
./test/test1/f1.txt
[root@centos8 ~]# find -iname f1.txt
./test/test1/f1.txt
[root@centos8 ~]# find / -name ".txt"
[root@centos8 ~]# find /var/ -name "log*"
/var/lib/selinux/targeted/active/modules/100/logadm
/var/lib/selinux/targeted/active/modules/100/logging
/var/lib/selinux/targeted/active/modules/100/logrotate
/var/lib/selinux/targeted/active/modules/100/logwatch
/var/lib/logrotate
/var/lib/logrotate/logrotate.status
/var/log

[root@centos8 ~]# find -regex ".*.txt$"
./test/test1/f1.txt
./f2.txt
2.4 根据属主、属组查找
  • -user Username   查找属主为指定用户(UID)的文件
  • -group Groupname 查找属组为指定组(GID)的文件
  • -uid UserID     查找属主为指定的UID号的文件
  • -gid GroupID   查找属组为指定的GID号的文件
  • -nouser       查找没有属主的文件
  • -nogroup     查找没有属组的文件
2.5 根据文件类型查找
  • -type TYPE

    TYPE包括:f普通文件、d目录、l链接文件、s套接字文件、b块设备、c字符设备、p管道文件

[root@centos8 ~]# find /home/ -type d -ls
 50332151      0 drwxr-xr-x   3  root     root           18 Mar 17 14:09 /home/
 51065618      0 drwx------   2  test     test           62 Mar 17 14:09 /home/test
2.6 空文件或目录

-empty

[root@centos8 ~]# find /var -type d -empty
/var/lib/games
/var/lib/misc
/var/lib/rpm-state
/var/lib/selinux/tmp
/var/lib/selinux/final
2.7 组合条件
  • 与:-a,默认多个条件是与关系
  • 或:-o
  • 非:-not !
[root@centos8 ~]# find /etc/ -type d -o -type l |wc -l 
283
[root@centos8 ~]# find /etc/ -type d -o -type l -ls |wc -l
78
[root@centos8 ~]# find /etc/ ( -type d -o -type l ) -ls |wc -l
283

德·摩根定律:

  • (非A)或(非B)=非(A且B) !A -o !B = !(A -a B)
  • (非A)且(非B)=非(A或B) !A -a !B = !(A -o B)
[root@centos8 ~]# find -user test -group test
[root@centos8 ~]# find -user test -not -group test
[root@centos8 ~]# find -user test -o -user luna
[root@centos8 ~]# find -not ( -user test -o -user luna )
[root@centos8 ~]# find / -user test -o -uid 777

[root@centos8 ~]# find ! ( -type d -a -empty ) | wc -l
19
[root@centos8 ~]# find ! -type d -o ! -empty | wc -l         
19

[root@centos8 ~]# find ! -user test ! -user luna
.
./.bash_logout
./.bash_profile

# 找出/tmp目录下,属主不是root,且文件名不以f开头的文件
[root@centos8 ~]# find /tmp ( -not -user root -a -not -name 'f*' ) -ls   
[root@centos8 ~]# find /tmp -not ( -user root -o -name 'f*' ) -ls 
2.8 排除目录

查找/etc/下,除/etc/sane.d目录的其他所有.conf后缀的文件

[root@centos8 ~]# find /etc/ -path '/etc/sane.d' -a -prune -o -name "*.conf"
/etc/resolv.conf
/etc/dnf/dnf.conf
/etc/dnf/plugins/copr.conf

查找/etc/下,除/etc/sane.d和/etc/fonts两个目录的所有.conf后缀的文件

[root@centos8 ~]# find /etc/ ( -path '/etc/sane.d' -o -path /etc/fonts ) -a -prune -o -name "*.conf"
/etc/resolv.conf
/etc/dnf/dnf.conf
/etc/dnf/plugins/copr.conf

排除/proc和/sys目录

[root@centos8 ~]# find / ( -path /sys -o -path /proc ) -a -prune -o -type f -a -mmin -1
/proc
/sys
2.9 根据文件大小来查找
  • -size [+|-]#UNIT   常用单位:k,M,G,c(byte),注意大小写敏感
  • #UNIT       表示(#-1,#],如:6k表示(5k,6k]
  • -#UNIT       表示[0,#-1],如:-6k表示[9.5k]
  • +#UINT      表示(#,∞),如:+6k表示(6k,∞)
[root@centos8 ~]# find / -size +10G
/proc/kcore
2.10 根据时间戳
  • 以“天”为单位

    • -atime [+|-]#
      #   表示[#,#+1)
      +#  表示[#+1,∞]
      -#   表示[0,#)
    • -mtime
    • -ctime
  • 以“分钟”为单位

    • -amin
    • -mmin
    • -cmin
2.11 根据权限查找

-perm [/l-]MODE

  • MODE   精确权限匹配
  • /MODE  任何一类(u,g, o)对象的权限中贝要能一位匹配即可,或关系,+从Centos 7开始淘汰
  • -MODE  每一类对象都必须同时拥有指定权限,与关系
  • 0     表示不关注

说明:

find -perm 755会匹配权限模式恰好是755的文件
只要当任意人有写权限时,find -perm /222就会匹配
只有当每个人都有写权限时,find -perm -222才会匹配
只有当其它人(other) 有写权限时,find -perm -002才会匹配

2.12 正则表达式
-regextype type
       Changes  the  regular expression syntax understood by -regex and -iregex
       tests which occur later on the  command  line.   To  see  which  regular
       expression types are known, use -regextype help.  The Texinfo documenta‐
       tion (see SEE ALSO) explains the meaning of and differences between  the
       various types of regular expression.
-regex pattern
       File name matches regular expression pattern.  This is a  match  on  the
       whole  path,  not  a  search.   For  example,  to  match  a  file  named
       `./fubar3', you can use the regular expression `.*bar.' or `.*b.*3', but
       not  `f.*r3'.  The regular expressions understood by find are by default
       Emacs Regular Expressions, but this can be changed with  the  -regextype
       option.

例:

[root@centos8 ~]# find /you/find/dir -regextype posix-expanded -regex "regex"
2.13 处理动作
  • -print   默认的处理动作,显示至屏幕
  • -ls     类似于对查找到的文件执行"ls -dils"命令格式输出
  • -fls file  查找到的所有文件的长格式信息保存至指定文件中,相当于-ls > file
  • -delete   删除查找到的文件,慎用!
  • -ok COMMAND {} ;  对查找到的每个文件执行由COMMAND指定的命令,对于每个文件执行命令之前,都会交互式要求用户确认
  • -exec COMMAND {} ; 对查找到的每个文件执行由COMMAND指定的命令
  • {}     用于引用查找到的文件名称自身

注意:不同文件夹上的同名文件可能会被覆盖

# 备份配置文件,添加.orig这个扩展名
[root@centos8 ~]# find -name ".conf" -exe cp {} {}.orig ;
# 提示删除存在时间超过3天以上的joe的临时文件
[root@centos8 ~]# find /tmp/ -ctime +3 -user joe -ok rm {} ;
# 在主目录中寻找可被其他用户写入的文件
[root@centos8 ~]# find ~ -perm -022 -exec chmod o-w {} ;
# 查找/data下权限为644,后缀为sh的普通文件,增加执行权限
[root@centos8 ~]# find /data -type f -pern 644 -name "*.sh" -exec chmod 755 {} ;

备份文件

[root@centos8 test]# ls
f1.txt  f2.txt  f3.txt
[root@centos8 test]# find . -name "*.txt" -exec cp {} {}.bak ;
[root@centos8 test]# ls
f1.txt  f1.txt.bak  f2.txt  f2.txt.bak  f3.txt  f3.txt.bak

删除文件

[root@centos8 test]# ls
f1.txt  f1.txt.bak  f2.txt  f2.txt.bak  f3.txt  f3.txt.bak
[root@centos8 test]# find . -name "f*" -exec rm {} ;             
[root@centos8 test]# ls
[root@centos8 test]# 

3 参数替换xargs

由于很多命令不支持管道|来传递参数, xargs用于产生某个命令的参数,xargs可以读入stdin的数据,并且以空格符或回车符将stdin的数据分隔成为参数

另外,许多命令不能接受过多参数,命令执行可能会失败,xargs可以解决

注意:文件名或者是其他意义的名词内含有空格符的情况

find经常和xargs令进行组合,形式如下:

find | xargs COMMAND

显示十个数字

[root@centos8 ~]# seq 10
1
2
3
4
5
6
7
8
9
10
[root@centos8 ~]# seq 10 | xargs
1 2 3 4 5 6 7 8 9 10

[root@centos8 ~]# echo {1..5}|xargs
1 2 3 4 5
[root@centos8 ~]# echo {1..5}|xargs -n1
1
2
3
4
5
[root@centos8 ~]# echo {1..5}|xargs -n2
1 2
3 4
5
[root@centos8 ~]# echo {1..5}|xargs -n3
1 2 3
4 5

批量创建用户

[root@centos8 ~]# echo user{1..7} | xargs -n1 useradd
[root@centos8 ~]# getent passwd 
root:x:0:0:root:/root:/bin/bash
luna:x:1001:1001::/home/luna:/bin/bash
user1:x:1002:1002::/home/user1:/bin/bash
user2:x:1003:1003::/home/user2:/bin/bash
user3:x:1004:1004::/home/user3:/bin/bash
user4:x:1005:1005::/home/user4:/bin/bash
user5:x:1006:1006::/home/user5:/bin/bash
user6:x:1007:1007::/home/user6:/bin/bash
user7:x:1008:1008::/home/user7:/bin/bash
[root@centos8 ~]# echo user{1..7} | xargs -n1 userdel -r
[root@centos8 ~]# getent passwd                         
root:x:0:0:root:/root:/bin/bash
luna:x:1001:1001::/home/luna:/bin/bash

查找特殊权限文件并按照大小排序

[root@centos8 ~]# find /bin/ -perm /7000|xargs ls -Sl 
---s--x--x. 1 root root    203928 Dec 13  2019 /bin/sudo
-rwsr-xr-x. 1 root root    156736 Nov  9  2019 /bin/gpasswd
-rwsr-xr-x. 1 root root    133928 Nov  9  2019 /bin/chage
-rwsr-xr-x. 1 root root     88488 Nov  9  2019 /bin/newgrp
-rwsr-xr-x. 1 root root     65904 Nov  9  2019 /bin/crontab
-rwsr-xr-x. 1 root root     62104 Nov  9  2019 /bin/su
-rwsr-xr-x. 1 root root     61856 Nov  9  2019 /bin/mount
-rwx--s--x. 1 root slocate  48552 May 11  2019 /bin/locate
-rwsr-xr-x. 1 root root     40728 Nov  9  2019 /bin/umount
-rwsr-xr-x. 1 root root     38680 May 11  2019 /bin/fusermount
-rwsr-xr-x. 1 root root     34928 May 11  2019 /bin/passwd
-rwsr-xr-x. 1 root root     31488 Nov 12  2019 /bin/pkexec
-rwxr-sr-x. 1 root tty      26080 Nov  9  2019 /bin/write

用字符NUL分割

[root@centos8 test]# ls
'a b'  'b c'   f1.txt   f2.txt
[root@centos8 test]# find -type f -name "*.txt"
./f1.txt
./f2.txt
[root@centos8 test]# find -type f -print0
./a b./b c./f1.txt./f2.txt[root@centos8 test]#
[root@centos8 test]# find -type f -print0|xargs -0 ls
'./a b'  './b c'   ./f1.txt   ./f2.txt
[root@centos8 test]# find -type f -print0|xargs -0
./a b ./b c ./f1.txt ./f2.txt
[root@centos8 test]# find -type f -print0|xargs -0 rm
[root@centos8 test]# ls

并发执行多个进程

[root@centos8 ~]# seq 100|xargs -i -P10 wget /root/test http://10.1.1.5/{}.html

并行下载视频

[root@centos8 ~]# seq 10|xargs -i -P3 you-get https://www.bilibili.com/video/BV1HZ4y1p78f?p={}

you-get是python开发的下载bilibili视频的工具,可自行安装体验

练习题:

1、查找/var目录下属主为root,且属组为mail的所有文件

[root@centos8 ~]# find /var/ -user root -group mail
/var/spool/mail

2、查找/var目录下不属于root、lp、 test的所有文件

[root@centos8 ~]# find /var/ ! -user root ! -user lp ! -user test
/var/lib/tpm
/var/lib/unbound
/var/lib/unbound/root.key
/var/lib/sss/db
/var/lib/sss/gpo_cache
/var/lib/sss/mc
/var/lib/sss/mc/passwd
/var/lib/sss/mc/group
/var/lib/sss/mc/initgroups
/var/lib/sss/pipes
/var/lib/sss/pipes/private
/var/lib/sss/pubconf
/var/log/sssd
/var/spool/mail/luna

3、查找/var目录 下最近1周内其内容修改过,同时属主不为root,也不是postfix的文件

[root@centos8 ~]# find /var/  -mtime -7 ! -user root ! -user test
/var/lib/unbound
/var/lib/sss/db
/var/lib/sss/mc
/var/lib/sss/mc/passwd
/var/lib/sss/mc/group
/var/lib/sss/mc/initgroups
/var/lib/sss/pipes
/var/lib/sss/pipes/private
/var/log/sssd
/var/spool/mail/luna

4、查找当前系统上没有属主或属组,且最近1个周内曾被访问过的文件

[root@centos8 ~]# find / ( -nouser -o -nogroup ) -atime -7
find: ‘/proc/14554/task/14554/fd/9’: No such file or directory
find: ‘/proc/14554/task/14554/fdinfo/9’: No such file or directory
find: ‘/proc/14554/fd/8’: No such file or directory
find: ‘/proc/14554/fdinfo/8’: No such file or directory
/var/spool/mail/test1
/home/test1
/home/test1/.bash_logout
/home/test1/.bash_profile
/home/test1/.bashrc

5、查找/etc目录下大于1M且类型为普通文件的所有文件

[root@centos8 ~]# find /etc/ -size +1M -type f
/etc/selinux/targeted/policy/policy.31
/etc/udev/hwdb.bin

6、查找/etc目录下所有用户都没有写权限的文件

[root@centos8 ~]# find /etc/ ! -perm /222

7、查找/etc目录下至少有一类用户没有执行权限的文件

[root@centos8 ~]# find /etc/ ! -perm -111

8、查找/etc/init.d目录下, 所有用户都有执行权限,且其它用户有写权限的文件

[root@centos8 ~]# find /etc/init.d/ -perm /113
/etc/init.d/