当前位置:首页>Linux>每天学一个Linux命令系列(19):find - 找文件王者,按时间/大小/权限精准搜索

每天学一个Linux命令系列(19):find - 找文件王者,按时间/大小/权限精准搜索

  • 2026-10-11 07:01:25
每天学一个Linux命令系列(19):find - 找文件王者,按时间/大小/权限精准搜索
运
运维少年 · 科技观察

这个命令是干啥的

find 是 Linux 上最强大的文件搜索命令,没有之一。

跟 locate 这种靠数据库的搜索不同,find 是实时在磁盘上遍历目录树,你告诉它去哪找、找什么,它就一个个翻。虽然慢了那么一点,但结果绝对准确。而且它的过滤条件多到离谱:文件名、大小、时间、权限、类型、所属用户,你想到的它基本都能做。

我刚开始用 find 的时候觉得挺笨的,不就找个文件吗?后来有一次线上出了问题,需要在 200G 的日志目录里找 30 天前的 .tar.gz 文件来清理,find 一条命令搞定,换成手动翻目录得翻到猴年马月。从那以后我就服了。

基本用法(3分钟上手)

按名字找:-name 和 -iname

# 在当前目录下找叫 readme.txt 的文件
find . -name "readme.txt"
# 找所有 .log 结尾的文件
find /var/log -name "*.log"
# -iname 忽略大小写(找 readme、Readme、README 等)
find . -iname "readme*"

按类型找:-type

# 只找文件(不包含目录)
find . -type f
# 只找目录
find . -type d
# 找符号链接
find . -type l

按大小找:-size

# 超过 100MB 的文件
find / -size +100M
# 小于 10KB 的文件
find . -size -10k
# 正好等于 1MB 的文件
find . -size 1M

这里的 + 表示大于,- 表示小于,不加就是等于。

单位的坑:k 是小写的千字节,M 和 G 是大写。

进阶骚操作

按时间找:-mtime、-atime、-ctime

这个我用的最多,尤其是清理旧日志的时候。

# 找7天前修改过的文件
find /var/log -name "*.log" -mtime +7
# 找1天内修改过的文件
find . -mtime -1
# 找刚好7天前访问过的文件
find . -atime 7

时间三兄弟的区别:

  • ·-mtime:文件内容修改时间
  • ·-atime:文件最后访问时间
  • ·-ctime:文件元数据(权限、属主等)改变时间

还有一个实用技巧:-mmin、-amin、-cmin 是按分钟算的,适合更精细的搜索。

# 最后30分钟内修改过的文件
find . -mmin -30

按权限找:-perm

# 找权限为 777 的文件
find / -type f -perm 0777
# 找其他用户有写权限的文件(模式:任何人都有w权限)
find / -type f -perm /o=w
# 找设置了 SUID 的可执行文件(安全扫描常用)
find / -type f -perm /4000

多条件组合

# 找超过500MB且7天前的日志文件
find /var/log -name "*.log" -size +500M -mtime +7
# 找属于 www-data 用户的 .php 文件
find /var/www -type f -name "*.php" -user www-data
# 找空文件或空目录
find . -empty

-exec:找到后直接执行操作

这是 find 的杀手锏功能。找到文件后可以直接对它们做操作。

# 找到 .tmp 文件并删除
find /tmp -name "*.tmp" -type f -exec rm {} \;

解释一下语法:{} 是占位符,find 会用找到的每个文件替换它。\; 是结束符,表示每条命令独立执行(分号在 shell 中有特殊意义,所以要加反斜杠转义)。

如果改成 + 结尾,就是批量传参:

# 和 xargs 类似,批量传参效率更高
find /tmp -name "*.tmp" -type f -exec rm {} +

-delete:直接删除

# 直接删除找到的文件(不用-exec)
find /tmp -name "*.tmp" -type f -delete

注意:-delete 非常直接,没有二次确认。建议先不加 -delete 跑一遍,确认结果正确再加。

我就吃过这个亏。有次想删 /tmp 下的 .tmp 文件,手滑写成了 find . -name "*.conf" -delete,结果当前目录下所有 .conf 文件没了。还好有 git 能恢复,不然就哭了。

-print0 配合 xargs

# 处理文件名带空格的情况
find /data -name "*.txt" -type f -print0 | xargs -0 rm

避坑指南

坑1:路径一定要写对

# find 的第一个参数是搜索起点
find . -name "*.txt"  # . 表示当前目录
find / -name "*.txt"  # / 表示整个文件系统(会很慢)

新手最容易犯的错:以为不写路径就会搜全盘。不会的,不写就用当前目录。

坑2:通配符要加引号

# 正确的写法
find . -name "*.log"

# 错误的写法(如果不巧当前目录有 .log 文件,shell 会先展开通配符)
find . -name *.log

不加引号的话,如果当前目录有 a.log,shell 会把这个命令变成 find . -name a.log,其他 .log 文件就找不到了。

坑3:权限问题

# 如果用非 root 用户搜 / 目录,会有很多 Permission denied 的报错
find / -name "*.conf" 2>/dev/null  # 把错误信息丢到黑洞

坑4:-delete 的陷阱

# -delete 隐含了 -depth,可能删除顺序和预期不一样
find . -name "*.log" -delete  # 没问题
find . -name "*.log" -type d -delete  # 目录是空的才会被删

而且 -delete 不能和 -prune 同时用,会报错。

坑5:find 和 exec 的参数顺序

# {} 和 \; 要写对,中间可能有空格
find . -name "*.txt" -exec cp {} /backup/ \;

习惯写法:-exec command {} \; 或 -exec command {} +,我把这个记成了固定搭配。

实战场景

场景1:清理 N 天前的旧日志

这是生产环境最常用的场景:

# 删除30天前的.log.gz文件
find /var/log/myapp -name "*.log.gz" -type f -mtime +30 -delete
# 更保守的做法:先查出来看看,确认再删
find /var/log/myapp -name "*.log.gz" -type f -mtime +30 -exec ls -lh {} \;
# (检查确认没问题后)
find /var/log/myapp -name "*.log.gz" -type f -mtime +30 -delete

场景2:找大文件做优化

# 找出根目录下所有超过 500MB 的文件
find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -rh -k5

这条命令用来定位什么文件最大,然后决定是清理还是归档。我在很多服务器上用它找过日志文件和备份文件,经常能释放几十 G 空间。

场景3:安全扫描

# 找所有 SUID 文件(普通用户能提权的风险点)
find / -type f -perm /4000 -ls 2>/dev/null
# 找属于 root 但其他用户可写的文件
find / -type f -user root -perm /o=w -ls 2>/dev/null

场景4:按权限批量修复

# 找所有 PHP 文件并设为 644
find /var/www -type f -name "*.php" -exec chmod 644 {} \;
# 找所有目录设为 755
find /var/www -type d -exec chmod 755 {} \;

场景5:找大文件脚本

#!/bin/bash
# 找出指定目录下最大的10个文件
TARGET_DIR=${1:-.}
echo "在 $TARGET_DIR 中查找最大的10个文件..."
find "$TARGET_DIR" -type f -exec ls -lh {} \; 2>/dev/null | \
    awk '{print $5, $NF}' | \
    sort -rh | \
    head -10

场景6:按时间归档备份

# 找出7天内修改过的配置文件做备份
find /etc -type f -mtime -7 -exec cp --parents {} /backup/ \;

今日作业

你的 CentOS 服务器的 /var/log 目录堆满了日志。请写一条 find 命令完成以下要求:

1. 在 /var/log 下查找
2. 文件名以 .log 结尾
3. 文件类型为普通文件
4. 超过 30 天没有被修改过(mtime > 30)
5. 文件大小大于 100MB
6. 执行删除操作

写出这一条命令。建议先不加 -delete 跑一遍验证结果。

E N D

运维少年 · 科技观察

最新文章

随机文章