前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Linux 命令:每日一学,文件查找之find命令实践

Linux 命令:每日一学,文件查找之find命令实践

作者头像
全栈工程师修炼指南
发布2024-10-10 16:14:21
发布2024-10-10 16:14:21
20600
代码可运行
举报
运行总次数:0
代码可运行

0x01 文件查找

1.locate 命令 - 使用文件索引数据库快速查找

2.updatedb 命令 - 更新文件系统数据库

描述:此命令是Linux中查找文件或目录的命令,它与 updatedb 命令都是来自于 mlocate 包,它是直接从数据库/var/lib/mlocate/mlocate.db 中搜索文件名,而不是直接在磁盘上搜寻,所以速度很快,支持模糊查找,但是缺点是数据库文件一般一天更新一次,所以有时候可能查不到最新的文件(非实时),也可以手动进行索引构建其需要遍历整个根文件系统,很消耗系统资源,所以在更新索引时通常在系统闲时。

weiyigeek.top-locate工具查询原理图

温馨提示:CentOS 7 版本以上默认已经安装,如果未安装可以使用 yum install mlocate 进行安装,Debian 系列系统默认需要手动安装,可执行 sudo apt install mlocate 进行安装。

语法参数

代码语言:javascript
代码运行次数:0
复制
# 语法
locate [OPTION]... [PATTERN]...
# 参数
-i, --ignore-case      配置时搜索时忽略大小写
-l, --limit, -n LIMIT  指定匹配输出(或计数)N 个条目
-r, --regexp REGEXP    搜索基本正则表达式regexp而不是模式(强大)
    --regex            patterns are extended regexps
-A, --all              仅打印与所有规则匹配的条目
-b, --basename         仅匹配路径名的基本名称
-c, --count            仅打印找到的条目数
-d, --database DBPATH  指定文件索引数据库文件 (which is /var/lib/mlocate/mlocate.db)
-e, --existing         仅打印当前存在文件的条目
-L, --follow           检查文件是否存在时遵循尾随符号链接(默认)
-m, --mmap             ignored, for backward compatibility
-P, --nofollow, -H     检查文件是否存在时,不要遵循尾随符号链接
-0, --null             输出时使用NUL分隔条目
-S, --statistics       don\'t search for entries, print statistics about each used database
-q, --quiet            report no error messages about reading databases
-s, --stdio            ignored, for backward compatibility
-w, --wholename        匹配整个路径名(默认)


# 语法
updatedb [OPTION]...
# 参数
-f, --add-prunefs FS           omit also FS
-n, --add-prunenames NAMES     omit also NAMES
-e, --add-prunepaths PATHS     omit also PATHS
-U, --database-root PATH       要存储在数据库中的子树(默认为"/")
-o, --output FILE              指定索引数据库存储路径 (default `/var/lib/mlocate/mlocate.db')
    --prune-bind-mounts FLAG   omit bind mounts (default "no")
    --prunefs FS               filesystems to omit from database
    --prunenames NAMES         directory names to omit from database
    --prunepaths PATHS         paths to omit from database
-l, --require-visibility FLAG  在报告文件之前检查可用性 (default "yes")

示例演示:

代码语言:javascript
代码运行次数:0
复制
# 1.强制更新索引数据库到  /var/lib/mlocate/mlocate.db 文件中
updatedb       
# 若是 Mac 系统则是如下路径
sudo /usr/libexec/locate.updatedb 
ll -h /var/lib/mlocate/mlocate.db
  # -rw-r----- 1 root slocate 6.1M Oct  9 17:36 /var/lib/mlocate/mlocate.db

# 2.配置 updatedb 命令的索引搜索限制
# 默认遵循 /etc/updatedb.conf 配置文件里的筛选规则,所以即使更新了数据库也不一定能locate到所要寻找的文件
PRUNE_BIND_MOUNTS = "yes"    #开启搜索限制
PRUNEFS    = "afs udf"       #搜索时不搜索的文件系统
PRUNENAMES = ".git .hg"      #搜索时不搜索的文件名
PRUNEPATHS = "/afs /tmp"     #搜索时不搜索的路径

weiyigeek.top-配置updatedb.conf文件设置搜寻规则

代码语言:javascript
代码运行次数:0
复制
# 3.使用 locate 命令进行文件查找
# 查找文件名或目录中带有 "conf" 的文件目录
locate conf
  # /var/lib/sss/pubconf
  # /var/lib/sss/db/config.ldb
  # /var/lib/sss/pubconf/krb5.include.d
  # /var/log/.backup/20230809-1691546195/chrony.conf

# 4.使用正则表达式进行文件查找,匹配以.conf结尾的文件
locate -r '\.conf$'
  # /var/log/.backup/20230809-1691546195/chrony.conf
  # /var/log/.backup/20230809-1691546195/limits.conf
  # /var/log/.backup/20230809-1691546195/pwquality.conf
  # /var/log/.backup/20230809-1691546195/sysctl.conf

# 5.使用正则表达式,忽略大小写查找文件,并输出10行匹配条目
locate -n 10 -ir '\.CONF$'
  # /etc/asound.conf
  # /etc/chrony.conf
  # /etc/dracut.conf
  # /etc/e2scrub.conf
  # /etc/fuse.conf
  # /etc/host.conf
  # /etc/idmapd.conf
  # /etc/ipsec.conf
  # /etc/kdump.conf
  # /etc/krb5.conf

# 6.只搜寻目录中包含 conf 字符的条目,注意反斜杠。
locate -b '\conf'
  # /etc/httpd/conf
  # /usr/lib/python3.7/site-packages/dnf/conf
  # /usr/lib64/sssd/conf

3.find 命令 - 实时查找文件或目录的高级工具

描述:此工具是Linux中最常用搜索文件或者目录的命令,其功能也是十分强大能从各个维度方面进行搜寻,例如,时间、文件大小、用户、权限等,并且可以按照文件名或目录名进行搜索,还可以针对以搜索到的文件目录做指定处理,这也凸显出此工具的强大之处。

语法参数

代码语言:javascript
代码运行次数:0
复制
# 用法
find [OPTION] ... [PATH]  [CONDITION]  [ACTION]

# [PATH] :即起始查找路径,. 表示当前目录,.. 表示上一级目录,/ 根目录,/etc/ 指定目录
# [CONDITION] :即搜索条件,例如根据文件名、用户、权限等进行搜索
# [ACTION]:即处理动作,例如,删除、修改等,默认是输出到屏幕

# 常用参数
-name    # 按照文件名搜索,可用通配符
-iname   # 按照文件名搜索,但不区分大小写
-regex "PATTERN"  # 按照正则表达式查询
-regextype emacs # 设置正则表达式语法,可选 emacs (this is the default), posix-awk, posix-basic, posix-egrep and posix-extended.

-inum  N  # 按照文件inode号搜索
-samefile # 按照相同inode号的文件搜索
-links N  # 按照文件链接数为N的搜索

-user    # 按照文件属主搜索
-group   # 按照文件属组搜索
-uid     # 按照文件属主uid搜索,例如 root 用户其 uid = 0
-gid     # 按照文件属组gid搜索,例如 root 用户其 gid = 0
-nouser  # 查找没有属主的文件
-nogroup # 查找没有属组的文件

-type f/d/l/s/b/c/p  # 按照文件类型搜索
  f 表示普通文件
  d 表示目录
  l 表示符号链接文件
  s 表示套接字文件  
  b 表示块设备文件
  c 表示字符设备文件
  p 表示管道设备文件
 
-perm [MODE]  # 按照文件目录权限搜索,精确查找
      -[u,g,o]=[MODE] # 按照文件权限搜索
      -[MODE]         # 例如,-222 只有当每个人都要写权限才会匹配
      +[MODE]         # 例如,+444  只要当任意一个人有读权限时就会匹配,注意 CentOS7 之前是使用 / 符号
      0              # 表示不关注

-size +/- N    # 按照文件文件大小搜索
      N        # 范围区间((N-1),N]文件大小单位为k,M,G
     -N        # 范围区间[0,(N-1)],文件大小单位为k,M,G
     +N        # 范围区间(N,-∞),文件大小单位为k,M,G


-atime/-amin  # 按照访问文件的时间搜索,其中 atime 表示天数,amin 表示分钟
    N         # 范围区间[N,N+1)
    +N        # 范围区间[N+1,∞]
    -N        # 范围区间[0,N)
-ctime/-cmin  # 按照改变文件属性的时间搜索
-mtime/-mmin  # 按照修改文件内容的时间搜索
-newer        # 列出被改参数指定的文件还要新的文件名称;
-newermt      # 列出指定时间之后被改创建的文件名称;

-empty  # 查找空文件或空目录

-path   # 指定目录路径可包含或者排除
-prune  # 表示排除 -path 参数指定的目录

-depth  # 指定搜索目录的深度,加上默认优先处理目录中的文件,后处理其目录
-mindepth   # 按照目录层级搜索,搜索的最小层级目录
-maxdepth   # 搜索的最大层级目录

-xdev   # 限制 find 命令只在当前文件系统中查找,而不跨越挂载点

# 常用条件
-a     # 逻辑与,按照逻辑组合条件搜索,多个条件搜索时,同时满足所有条件
-o     # 逻辑或,多个条件搜索时,满足任意一个条件
! 或 -not      # 逻辑非,排除指定条件搜索

# 常用动作
-print    # 默认处理动作,按换行输出至屏幕
-print0   # 不换行打印find的结果,结果之间采用空格进行分割;
-fprint0 file # 将find的结果存入文件
-ls       # 对查找到的文件执行类似于 ls -l 的命令
-fls /tmp/test.log # 存入执行ls -aihl 命令后输出到文件
-delete   # 删除查找到文件
-exec COMMAND {} \;  # 或者将\; 替换为 +,{} 代表匹配搜寻到的文件
-ok COMMAND {} \;    # 或者将\; 替换为 + ,{} 代表匹配搜寻到的文件,但是每次执行都会以交互方式要求用户确认是否执行命令

温馨提示:find 命令可使用通配符(完全匹配)是在系统当中搜索符合条件的文件名,常用通配符如下所示:

代码语言:javascript
代码运行次数:0
复制
* 匹配任意内容(任意多个字符)
? 匹配任意一个字符
[] 匹配任意一个中括号内的字符 x[ab]->xa或者xb
[-] 匹配中括号中任意一个字符,-代表一个范围 例如,[a-z]代表匹配一个小写字母
[^] 逻辑非,表示匹配不是中括号内的一个字符 例如[^0-9]代表匹配一个不是数字的字符

温馨提示:find 命令可使用逻辑运算符对条件进行组合,例如,德.摩根定律 !A ∧ !B = ! ( A v B) , !A v !B = ! (A ∧ B) 类比于find的逻辑运算符则是 !A -a !B = ! (A -o B)!A -o !B = ! (A -a B)

实践案例

  • 1.搜寻当前目录所有嵌套的文件,报考空目录
代码语言:javascript
代码运行次数:0
复制
$ tree  # 查看示例目录结构
  .
  ├── demo
  │   ├── 1
  │   │   └── test.txt
  │   ├── 2
  │   │   └── test.txt
  │   ├── 3
  │   │   └── test.txt
  │   └── empty
  └── redisinsight-1.13.0.yaml
  
$ find .  # 默认搜索当前目录,先返回目录本身,再返回目录下的文件
  .
  ./demo
  ./demo/1
  ./demo/1/test.txt
  ./demo/3
  ./demo/3/test.txt
  ./demo/2
  ./demo/2/test.txt
  ./redisinsight-1.13.0.yaml

$ find . -depth # 默认搜索当前目录,则是先返回目录下的文件,再返回目录本身
  ./demo/1/test.txt
  ./demo/1
  ./demo/3/test.txt
  ./demo/3
  ./demo/2/test.txt
  ./demo/2
  ./demo
  ./redisinsight-1.13.0.yaml
  .

$ find . -empty # 显示目录为空,或者文件为空的文件
  ./demo/empty
  ./demo/1/test.txt
  ./demo/3/test.txt
  ./demo/2/test.txt

find . | grep .txt # 可使用管道符再次进行过滤,实际上不使用grep也可以达到效果
  • 2.指定要搜索目录的层级
代码语言:javascript
代码运行次数:0
复制
# 搜索 /etc/ 目录下二级到三级目录
find /etc/ -maxdepth 3 -mindepth 2 -type d      # 指定搜索目录的层级
find / -name "*tomcat.txt" -maxdepth 1 -print   # 在层级一中查询文件名包含tomcat的txt文件
  • 3.通过指定文件名称(通配符)进行搜寻
代码语言:javascript
代码运行次数:0
复制
find / -name *.git           # 匹配所有以.git结尾的文件
find / -name "ab[cd]"        # 匹配abc或abd
find / -iname SShd_config    # 不区分大小找寻
  # /usr/share/openssh/sshd_config
  • 4.按照指定文件类型搜寻,前面我们提到过的七种文件类型,此处就不在累述了。
代码语言:javascript
代码运行次数:0
复制
find . -type f      # 只查找匹配文件
find . -type d      # 只查找匹配目录
find / -type l -ls  # 查找软连接及其指向:
  • 5.按照文件所有者或所有组来搜索
代码语言:javascript
代码运行次数:0
复制
find /root -user root    # 是找root目录下所有者为root的文件
find /root -group root   # 是找root目录下所属组为root的文件
find /root -nonuser      # 是找root目录下没有所有者的文件
find / -nogroup -print   # 查找不属于任何用户组的文件:
  • 6.按照文件权限来搜索,注意三种特殊权限,分别是SUID 4SGID 2 SBIT 1
代码语言:javascript
代码运行次数:0
复制
find / -perm -o=w                      # 查找所有者有 w 权限的文件
find / -perm 0755                      # 查找 rwxr-xr-x 权限的文件 (精准查找)

find / -uid 0 -perm -4000             # 查找 uid 为0 且拥有 SUID 权限的文件
find / -user root -perm -4000 -print  # 查找有 SUID 权限 root 文件 
find / -group root -perm -2000 -print # 查找有 SGID 权限 root 文件
find / -perm -1000 -print             # 查找有 SBIT 权限文件
  • 7.按照大小来搜索
代码语言:javascript
代码运行次数:0
复制
find 【搜索范围】-size (+/-) *(k/M)  #小写k是kB,大写M是MB
find /root -size 10k                  # 查找root目录下大小(9KB,10kB]的文件
find /root -size +10k                 # 查找root目录下大小大于10kB的文件
find /root -size +10k -o -size 10k    # 查找root目录下大小大于或者等于10kB的文件
find /root -size +20k -a -size -50k   # 查找大于20KB且小于49kB大小的文件
find /root -size -20k -o -size +50K    # 查找小于等于19KB或者大于50kB的文件
  • 8.按照时间来搜索,可使用天或者分钟替代
代码语言:javascript
代码运行次数:0
复制
find /root -mtime +10    #是查找十天前修改的文件
find /root -mtime -10    #是查找十天内修改的文件
find /root -mtime -0.5   #是查找0.5天内修改的文件
find /root -mtime 10     #是查找第十天修改的文件
# 同理
find /root -cmin +10     #是查找10分钟前修改的文件

weiyigeek.top-size与mtime,cmin条件助记符图

  • 9.利用逻辑组合条件进行搜寻(多条件查询或、与、非)
代码语言:javascript
代码运行次数:0
复制
find / -perm -4000 -o -perm -2000 -print               # 查找 为 SUID 或者 为SGID 的文件:
find . ! -user weiyigeek -a ! -user minio              # 查找当前目录下不属于weiyigeek和minio用户的文件
find . ! \(-user weiyigeek -o -user minio\)            # 查找当前目录下不属于weiyigeek和minio用户的文件
find / \( -not -user root -a -not -name 'fstab' \) -ls # 查找tmp目录下,所属主不是root且文件名不是fstab的文件
find / -not \( -user root -o -name 'fstab' \) -ls
  • 10.按照i节点来搜索
代码语言:javascript
代码运行次数:0
复制
find 【搜索范围】-inum 【-/+ i节点号】                        # 注意下面括号之间有空格
find / \( -inum +4000000000 -a -inum -4026532147 \) -l        # 搜寻节点号大于400000000且小于4026532147
find / \( -inum +4000000000 -a  -not -inum -4026532147 \) -l  # 搜寻节点号大于400000000且不下于4026532147
  • 11.排除查找指定目录
代码语言:javascript
代码运行次数:0
复制
# 在当前目录下排除 BAK 目录(子目录)中的jpg文件(排除多个目录)
find . -path "*/BAK" -prune -o -type f -name *.jpg > /tmp/2019.txt

# 在当前目录下排除./code之外的子目录内搜索 txt文件,并打印出文件,可不加 -print 缺省
find . -path "./code" -prune -o -name "*.txt" -print

# 在当前目录及除code和code2之外的子目录中查找txt文件
find . \(-path "./code" -o -path "./code2" \) -prune -o -name "*.txt" -print    
  • 12.换行或不换行显示查找结果,或将查询结果以ls -dils 命令返回风格输出到文件中
代码语言:javascript
代码运行次数:0
复制
find . -type f -name "*.yaml" -print  # 换行输出,缺省
find . -type f -name "*.log" -print0  # 不换输出,以空格分隔
  ./var/lib/docker/overlay2/716be24950255cd6668ac1ddbb662f2543d7a8bd6a5feb34d74f3d108ae3262b/diff/usr/lib/node_modules/npm/node_modules/socks/yarn-error.log ./var/log/boot.log ./var/log/tuned/tuned.log

# 找到文件以长连接格式存入到文件中
find /root -name ding*y -fls www.txt && cat www.txt  
  # 139002    4 -rwxr-xr-x   1 root     root          994 May 13 22:40 /root/dingding.py
  • 13.删除查询到的文件(慎用)
代码语言:javascript
代码运行次数:0
复制
# 查找 root 目录下使用 ding开头的sh文件并删除
find /root -name ding*.sh -delete
# 或者
find /root -name ding*.sh -exec rm -rf {} \;  
  • 14.使用 -exec/-ok 命令用来继续处理搜索到的文件(非常重要)
代码语言:javascript
代码运行次数:0
复制
#其中'{}'代表找到的文件,删除满足条件的文件或者目录,注意,由于 ; 在命令行中有特殊意义,所以这里使用\来转义。
find ./ -name "*.log" -exec rm -f {} \; 

# 查找20~50kB的文件,并列出详细信息
find /root -size +20k -a -size -50k -exec ls -lh {} \;      

# 查找当下目录下所有文件,并列出详细信息
find . -type f -exec ls -l '{}' ';'  

# 查找当下目录下一天之前的文件并统计其行数
find . mtime +1 -exec wc -l {}  \;
  # 6 ./.nvm/versions/node/v11.12.0/lib/node_modules/pm2/node_modules/pm2-axon-rpc/.travis.yml

# 查询当下目录下五分钟内创建过的文件并重名以.new结尾
find . cmin -5 -ok mv {} {}.new \;

# 查找/tmp目录下所有文件,并更改所属主和组
find /tmp -nogroup -ok chown root:nobaby {} \;

# 注意:-exec 参数执行查找后的相应文件处理结尾可以采用`+`来替换`\;`
find . -type f -exec ls -alh {} && echo {} +
  # -rw------- 1 root root 322M Feb 24 13:31 ./fanal-3744861088
  • 15.该删除文件、目录下的所有空目录(清空回收站还是不错的)
代码语言:javascript
代码运行次数:0
复制
# 删除回收站
find ~/.trash -delete
# 删除当前目录下的所有文件
$find . -type f -delete
# 删除空目录以及指定路径下的空目录
$find . -type d -empty -delete
$find ~/.trash -type d -delete
  • 16.查找比指定时间,或者比指定文件的时间还新的文件。
代码语言:javascript
代码运行次数:0
复制
# 查找指定时间以后的文件
find /tmp/ -type f -newermt 2024-02-27

# 查找/etc目录中文件日期比/etc/passwd还新的文件
find /etc -newer /etc/passwd
  # /etc
  # /etc/shadow
  # /etc/rc2.d
  # /etc/rc2.d/S01ssh

实践使用

  • 示例1.找出/app/weiyigeek/目录下48小时的日志并压缩,以及将十五天前的日志删除
代码语言:javascript
代码运行次数:0
复制
find /app/weiyigeek/ -mtime +1 -name "itmweb.log_2017-*.log" -exec gzip {} \; 
find /app/weiyigeek/ -mtime +15 -name "host-manager*.gz" -exec rm -rf {} \; 
  • 示例2.遍历/tmp目录下的多个图片格式,并将其路径与后缀进行多次替换。
代码语言:javascript
代码运行次数:0
复制
for i in $(find /tmp -name *.png -o -name *.jpg -o -name *.jpeg -o -name *.tiff); do img1=${i/.png/.webp}; echo ${img1/image/convert}; done
  /tmp/convert/1.jpg
  /tmp/convert/2.webp
  • 示例3.查找指定目录下所有复合条件的文件,并按照指定字符串匹配。
代码语言:javascript
代码运行次数:0
复制
find log-studentcenter-{0..11}-*/logs/StudentCenter/info.2023-01-*.log -exec grep -P '50030****222|500108****2' {} \; | grep ".CjxxController.getCj:" >> /tmp/weiyigeek.logs
find log-studentcenter-{0..11}-*/logs/StudentCenter/info.2022-06-*.log -exec grep "resetPassword" {} \; | grep "pz" >> /tmp/pz-resetPassword.logs
find log-studentcenter-{0..11}-*/logs/StudentCenter/info.2023*.log -exec grep "resetPassword" {} \; | grep "gkys" >> /tmp/gkys-resetPassword.logs
  • 示例4.在执行某个文件同步操作(如备份)后,检查以确定哪些文件在同步过程中被修改或者创建
代码语言:javascript
代码运行次数:0
复制
# 命令流程
1.获取当前的日期和时间,并以特定格式存储到变量 T 中。
2.执行 rsync.sh 脚本以进行文件同步操作。
3.查找在 rsync.sh 执行后修改过的所有文件和目录。

# 查找在 rsync.sh 执行后修改过的所有文件和目录
find /var/log/ -name *.log
echo '#!/bin/bash' > rsync.sh
echo "rm -rf /tmp/*.log" >> rsync.sh
echo "find /var/log/ -name *.log -exec cp -a {} /tmp/ \;" >> rsync.sh
echo "touch /tmp/weiyigeek.top.log.{1..3} \;" >> rsync.sh
chmod +x ./rsync.sh 
T="$(date "+%F %T.%N")";./rsync.sh; find / -xdev -newermt "$T"

# 命令浅析
$ T="(date "+%F %T.%N")"
  date "+%F %T.%N": 这个命令使用 date 工具获取当前的日期和时间,格式为:
  %F: 表示完整的日期(YYYY-MM-DD)
  %T: 表示完整的时间(HH:MM:SS)
  %N: 表示当前秒内的纳秒值
  T="$(…)": 将上述格式化的日期时间字符串赋值给变量 T。
echo $T
  # 2024-10-10 10:25:46.937895290

$ ./rsync.sh;
  ;: 分隔符,用于将多个命令串联在一起执行。
  ./rsync.sh: 执行当前目录下名为 rsync.sh 的脚本。这个脚本通常用于同步文件或目录。
  
$ find / -xdev -newermt "$T"
  find /: 从根目录 / 开始查找文件和目录。
  -xdev: 选项限制 find 命令只在当前文件系统中查找,而不跨越挂载点。这意味着如果有其他文件系统挂载(如 USB 驱动器),find 将不会在这些文件系统上进行查找。
  -newermt "$T": 这个选项会查找所有在 $T 指定的时间之后修改过的文件或目录。这里 $T 是之前定义的时间戳。

总结说明

Linux 系统中文件查找命令使用建议,若要非实时查询可使用 locate 命令,若要实时查询可使用 find 命令,附上两个命令快速学习的大纲脑图。

weiyigeek.top-locte与find命令脑图

若文章写得不错,不要吝惜手中转发,点赞、在看,若有疑问的小伙伴,可在评论区留言你想法哟💬!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈工程师修炼指南 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 文件查找
    • 1.locate 命令 - 使用文件索引数据库快速查找
    • 2.updatedb 命令 - 更新文件系统数据库
    • 3.find 命令 - 实时查找文件或目录的高级工具
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档