[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ]
0x00 前言简述
描述:前面我们一些学习了Linux文件内容查看、分隔列、排序、统计等命令,相信认真学习实践过的看友都已经初步掌握了吧,今天我们继续学习下Linux中我们常常用于文件查找过滤的相关命令,即 locate
命令 与 find
命令,帮助初学者快速掌握最基础的文件查找运维技能。
原文地址:Linux 命令:每日一学,文件查找之find命令实践
此 Linux 命令 | 系列
文章将作为《#运维从业必学》专栏辅助学习知识,这是也是每位Linux运维工程师必须掌握的基础知识,作者耗费心力、时间进行总结,希望对大家有所帮助,所以若有帮助还请多多关注作者,并鼓励作者创造更多实践文章吧。
-
Linux 运维 | 1.从零开始,服务器远程连接与基础命令学习实践
-
Linux 运维 | 2.从零开始,文件系统目录结构及文件目录管理学习实践
-
Linux 运维 | 3.从零开始,用户和用户组管理实践
-
Linux 运维 | 4.从零开始,文件目录特殊权限管理实践
-
Linux 运维 | 5.从零开始,编辑器之神 vi/vim 速成指南
-
Linux 运维 | 6.从零开始,Shell编程中正则表达式 RegExp 速成指南
-
运维学习 | Linux 命令大全,从A到Z
-
Linux 命令 | 运维必学,文件目录管理操作命令实践集锦
-
Linux 命令 | 运维必学,用户和组管理命令实践集锦
-
Linux 命令 | 每日一学,文件目录特殊权限相关命令集锦
-
Linux 命令 | 每日一学,文本处理之文件内容查看实践
-
Linux 命令 | 每日一学,文本处理之内容分割排序实践
-
Linux 命令 | 每日一学,文本处理之内容统计比较实践
-
Linux 命令 | 每日一学,文本处理三剑客之grep命令实践
废话不多说,实践为王!
0x01 文件查找
1.locate 命令 - 使用文件索引数据库快速查找
2.updatedb 命令 - 更新文件系统数据库
描述:此命令是Linux中查找文件或目录的命令,它与 updatedb
命令都是来自于 mlocate 包,它是直接从数据库/var/lib/mlocate/mlocate.db
中搜索文件名,而不是直接在磁盘上搜寻,所以速度很快,支持模糊查找,但是缺点是数据库文件一般一天更新一次,所以有时候可能查不到最新的文件(非实时),也可以手动进行索引构建其需要遍历整个根文件系统,很消耗系统资源,所以在更新索引时通常在系统闲时。
温馨提示:CentOS 7 版本以上默认已经安装,如果未安装可以使用 yum install mlocate
进行安装,Debian 系列系统默认需要手动安装,可执行 sudo apt install mlocate
进行安装。
语法参数
# 语法
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")
示例演示:
# 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" #搜索时不搜索的路径
# 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中最常用搜索文件或者目录的命令,其功能也是十分强大能从各个维度方面进行搜寻,例如,时间、文件大小、用户、权限等,并且可以按照文件名或目录名进行搜索,还可以针对以搜索到的文件目录做指定处理,这也凸显出此工具的强大之处。
语法参数
# 用法
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 命令可使用通配符(完全匹配)是在系统当中搜索符合条件的文件名,常用通配符如下所示:
* 匹配任意内容(任意多个字符)
? 匹配任意一个字符
[] 匹配任意一个中括号内的字符 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.搜寻当前目录所有嵌套的文件,报考空目录
$ 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.指定要搜索目录的层级
# 搜索 /etc/ 目录下二级到三级目录
find /etc/ -maxdepth 3 -mindepth 2 -type d # 指定搜索目录的层级
find / -name "*tomcat.txt" -maxdepth 1 -print # 在层级一中查询文件名包含tomcat的txt文件
-
3.通过指定文件名称(通配符)进行搜寻
find / -name *.git # 匹配所有以.git结尾的文件
find / -name "ab[cd]" # 匹配abc或abd
find / -iname SShd_config # 不区分大小找寻
# /usr/share/openssh/sshd_config
-
4.按照指定文件类型搜寻,前面我们提到过的七种文件类型,此处就不在累述了。
find . -type f # 只查找匹配文件
find . -type d # 只查找匹配目录
find / -type l -ls # 查找软连接及其指向:
-
5.按照文件所有者或所有组来搜索
find /root -user root # 是找root目录下所有者为root的文件
find /root -group root # 是找root目录下所属组为root的文件
find /root -nonuser # 是找root目录下没有所有者的文件
find / -nogroup -print # 查找不属于任何用户组的文件:
-
6.按照文件权限来搜索,注意三种特殊权限,分别是
SUID 4
、SGID 2
和SBIT 1
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.按照大小来搜索
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.按照时间来搜索,可使用天或者分钟替代
find /root -mtime +10 #是查找十天前修改的文件
find /root -mtime -10 #是查找十天内修改的文件
find /root -mtime -0.5 #是查找0.5天内修改的文件
find /root -mtime 10 #是查找第十天修改的文件
# 同理
find /root -cmin +10 #是查找10分钟前修改的文件
-
9.利用逻辑组合条件进行搜寻(多条件查询或、与、非)
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节点来搜索
find 【搜索范围】-inum 【-/+ i节点号】 # 注意下面括号之间有空格
find / \( -inum +4000000000 -a -inum -4026532147 \) -l # 搜寻节点号大于400000000且小于4026532147
find / \( -inum +4000000000 -a -not -inum -4026532147 \) -l # 搜寻节点号大于400000000且不下于4026532147
-
11.排除查找指定目录
# 在当前目录下排除 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 命令返回风格输出到文件中
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.删除查询到的文件(慎用)
# 查找 root 目录下使用 ding开头的sh文件并删除
find /root -name ding*.sh -delete
# 或者
find /root -name ding*.sh -exec rm -rf {} \;
-
14.使用 -exec/-ok 命令用来继续处理搜索到的文件(非常重要)
#其中'{}'代表找到的文件,删除满足条件的文件或者目录,注意,由于 ; 在命令行中有特殊意义,所以这里使用\来转义。
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.该删除文件、目录下的所有空目录(清空回收站还是不错的)
# 删除回收站
find ~/.trash -delete
# 删除当前目录下的所有文件
$find . -type f -delete
# 删除空目录以及指定路径下的空目录
$find . -type d -empty -delete
$find ~/.trash -type d -delete
-
16.查找比指定时间,或者比指定文件的时间还新的文件。
# 查找指定时间以后的文件
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小时的日志并压缩,以及将十五天前的日志删除
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目录下的多个图片格式,并将其路径与后缀进行多次替换。
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.查找指定目录下所有复合条件的文件,并按照指定字符串匹配。
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.在执行某个文件同步操作(如备份)后,检查以确定哪些文件在同步过程中被修改或者创建
# 命令流程
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 命令,附上两个命令快速学习的大纲脑图。
原文地址:Linux 命令:每日一学,文件查找之find命令实践
若文章写得不错,不要吝惜手中转发,点赞、在看,若有疑问的小伙伴,可在评论区留言你想法哟💬!
温馨提示:作者最近10年的工作学习笔记(涉及网络、安全、运维、开发),需要学习实践笔记的看友,可添加作者账号[WeiyiGeeker],当前价格¥199,除了获得从业笔记的同时还可进行问题答疑以及每月远程技术支持,希望大家多多支持,收获定大于付出!
如果此篇文章对你有帮助,请你将它转发给更多的人!
学习推荐 往期文章
-
🔥【最新】DBA | 如何将 .bak 的数据库备份文件导入到SQL Server 数据库中?
-
🔥【最新】DBA | 如何将 .mdf 与 .ldf 的数据库文件导入到SQL Server 数据库中?
-
🔥【最新】运维Tips | 巧妙解决,银河麒麟V10 SP3系统安装后无法通过许可信息
-
💡【相关】Linux 运维 | 6.从零开始,Shell编程中正则表达式 RegExp 速成指南