AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

find —— 按各种条件找文件

一句话定义

find 在文件系统里递归找文件——按名字、时间、大小、权限、所有者...等条件。比 ls + grep 灵活百倍。结合 -exec 或 xargs 可以对找到的文件批量操作。

典型场景

  • 找最近修改的文件:find /var/log -mmin -10
  • 找大文件:find / -size +1G
  • 清旧备份:find /backup -name '*.bak' -mtime +30 -delete
  • 找空文件 / 空目录
  • 找权限不对的文件:find / -perm -4000 (setuid)
  • 找属于某用户的文件

基本语法

find <path> [conditions] [actions]
find .                              # 当前目录所有
find /var/log                       # /var/log 下所有
find /var/log -name "*.log"          # 按名字

按名字 / 路径

find . -name "*.log"                            # 按文件名(glob)
find . -iname "*.LOG"                            # ignore case
find . -name "test*" -o -name "*.bak"            # OR
find . -path "*/node_modules/*"                  # 按完整路径匹配
find . -not -name "*.log"                        # 取反
find . ! -name "*.log"                           # 同上
find . -regex '.*\.\(log\|bak\)$'                 # 正则

按文件类型

find . -type f                                  # 普通文件(**最常用**)
find . -type d                                   # 目录
find . -type l                                   # 软链接
find . -type b                                   # 块设备
find . -type c                                   # 字符设备
find . -type s                                   # socket
find . -type p                                   # pipe

按时间(实战最常用)

选项含义
-mtime文件内容修改时间(按天)
-atime文件访问时间(按天)
-ctime文件元数据改变时间(按天,含权限、ownership 变化)
-mmin / -amin / -cmin同上,按分钟
-newer file比 file 新
find . -mtime 0                                 # 今天改的(24h 内)
find . -mtime -7                                 # 7 天内改的
find . -mtime +7                                 # 7 天前改的
find . -mtime +30 -mtime -90                     # 30 到 90 天之间

find . -mmin -10                                  # 最近 10 分钟
find . -newer /tmp/marker                         # 比 marker 文件新

# 一组组合
find /tmp -name "*.tmp" -mtime +1                 # 1 天以上的 .tmp

-mtime -7 是 "less than 7 days ago" = 最近 7 天内。+7 是 "more than" = 超过 7 天前。- 是近期、+ 是久远。


按大小

find . -size +1G                                # 大于 1GB
find . -size -1k                                 # 小于 1K
find . -size +100M -size -1G                     # 100M 到 1G 之间
find . -size 0                                    # 空文件

单位:c(字节)、k、M、G、b(512 字节块,默认)。

排查"哪个文件占空间":

find / -xdev -size +1G -exec ls -lh {} \; 2>/dev/null | head

-xdev 不跨文件系统(避免进 /proc / /tmpfs)。


按所有者 / 权限

find . -user alice                              # 属于 alice
find . -group dev                                # 属于 dev 组
find . -nouser                                    # 没归属(用户被删了)
find . -nogroup

find . -perm 644                                  # 权限正好 644
find . -perm -644                                  # 权限**至少**含 644 的位
find . -perm /222                                  # 权限**任一**含 220 等 group write 位

# 安全审计
find / -perm -4000 2>/dev/null                     # setuid 文件
find / -perm -2000 2>/dev/null                     # setgid
find / -perm -002 -type f 2>/dev/null              # 全局可写文件(**安全风险**)

按深度限制

find . -maxdepth 1                              # 只当前一层(不递归)
find . -maxdepth 2                              # 最多两层
find . -mindepth 2                               # 至少两层
find . -maxdepth 1 -type f                       # 当前层的所有普通文件

-maxdepth 1 等价 ls -A,但条件查询能力强得多。


组合:-and -or -not

find . -name "*.log" -and -mtime -1              # AND(默认)
find . -name "*.log" -o -name "*.bak"             # OR
find . -not -name "*.tmp"                         # NOT

# 括号组合(要转义)
find . \( -name "*.log" -o -name "*.bak" \) -mtime +7

注意 ( ) 在 shell 里要转义为 \( \) 或加引号 '('。


行动 -exec / -delete / -print

-print(默认行为)

find . -name "*.log"
# 等价
find . -name "*.log" -print

-delete(危险)

find /tmp -name "*.tmp" -mtime +1 -delete         # 删 1 天以上的 .tmp
# 删之前先 dry-run
find /tmp -name "*.tmp" -mtime +1                  # 看会删什么
find /tmp -name "*.tmp" -mtime +1 -delete          # 真删

必先 -print 看一遍再 -delete——find 路径错了能删整个系统。

-exec command {} \;

find . -name "*.log" -exec ls -lh {} \;            # 对每个找到的跑 ls
find . -name "*.bak" -exec rm {} \;                 # 删(等价 -delete 但慢)
find . -name "*.py" -exec wc -l {} \;               # 统计行数

{} 是占位符(每次替换为找到的文件名)。\; 是命令结尾(必须转义)。

-exec command {} +

find . -name "*.log" -exec grep "ERROR" {} +
# 把多个文件一次性传给 grep(比 \; 快很多)

+ vs \;:

  • \; —— 每个文件单独执行一次命令(慢)
  • + —— 多个文件一起执行(快,等价 xargs 行为)

+ 优先,除非命令不接受多文件参数。

-exec vs xargs

# -exec 方式
find . -name "*.log" -exec rm {} +

# xargs 方式(更快、更灵活)
find . -name "*.log" -print0 | xargs -0 rm

后者支持 -P 并行(见 xargs.md)。


实战例子

1. 清磁盘:找大文件

find / -xdev -type f -size +100M 2>/dev/null \
  | xargs -I{} ls -lh {} \
  | sort -k5 -hr | head

或者更整洁:

find / -xdev -type f -size +100M -exec du -h {} + 2>/dev/null \
  | sort -hr | head

2. 清旧日志 / 备份

# 找 30 天以上的日志
find /var/log -name "*.gz" -mtime +30 -print

# 确认无误后
find /var/log -name "*.gz" -mtime +30 -delete

3. 找哪些 yaml 含某个关键字

find . -name "*.yaml" -exec grep -l "image:" {} +
# -l 只显示文件名
find . -name "*.yaml" -exec grep -Hn "imagePullPolicy" {} +
# -H 加文件名前缀、-n 加行号

4. 找最近改动的文件(排查改动来源)

find /etc -mtime -1 -type f                       # 最近 24 小时改的配置
find /etc -mmin -10 -type f                        # 最近 10 分钟

5. 找空目录 / 空文件

find . -type d -empty                             # 空目录
find . -type f -empty                              # 空文件

6. 找权限不对的私钥

find ~/.ssh -name "id_*" -not -name "*.pub" -perm /077 \
  -exec ls -l {} \;
# /077 = 任何 group / other 可读 / 写 / 执行
# 私钥应该 600,否则 ssh 拒用

7. 找 K8s manifest 里某种资源

find . -name "*.yaml" -exec grep -l "kind: Deployment" {} +

8. 找 SUID 二进制(安全审计)

find / -perm -4000 -type f 2>/dev/null
# /usr/bin/passwd
# /usr/bin/sudo
# ...

-xdev 不跨文件系统

K8s 节点 /var/lib/kubelet/... 下有几千个 mount,find 进去会爆量:

find / -name "config.yaml"                        # 会进所有 mount
find / -xdev -name "config.yaml"                  # 只在根分区

通常 -xdev + 起点目录限制。或者用 --prune-mounts(新版 GNU find)。


提速:-prune 排除目录

# 找文件、但跳过 .git / node_modules / venv
find . \( -name .git -o -name node_modules -o -name venv \) -prune -o -name "*.py" -print

-prune 让 find 不进入那个目录。比"找完再过滤"快很多。

或者更现代:用 fd:

fd "\.py$"                                       # 默认 respect .gitignore、快

但远端服务器不一定有 fd,find 永远在。


常见踩坑

坑 1:-mtime 单位是天、不是 24 小时

find . -mtime 0                                  # "今天"

-mtime 0 是 0-24 小时前,不是日历"今天"。8 点钟跑、能找到昨晚 10 点的(< 24 小时)。

-daystart 改成"日历天":

find . -daystart -mtime 0                         # 今天 0 点到现在改的

坑 2:路径错 + -delete = 灾难

find / -name "*.tmp" -delete                      # 整个系统所有 .tmp

/ 起点 + 没 -xdev + -delete。

防御:

  • 先 -print 看一遍
  • 路径写绝对、起点尽量小
  • 不熟悉时用 -ok 替代 -exec(每次确认)
find /tmp -name "*.tmp" -ok rm {} \;
# < rm ... /tmp/a.tmp > ?                          ← y/n 确认

坑 3:-name 是 glob 不是正则

find . -name "test.*"                             # OK,glob 中 * 是 0+ 字符
find . -name ".*\.log"                            # ❌ glob 不认 \.

正则用 -regex:

find . -regex '.*\.\(log\|bak\)$'

坑 4:忘了引号让 shell 先展开

find . -name *.log                                # shell 先展开 → 当前目录有 a.log b.log 就变成 find . -name a.log b.log
find . -name "*.log"                              # ✅
find . -name \*.log                               # ✅

-name 后面的模式永远加引号。

坑 5:-exec 后忘了 \;

find . -name "*.log" -exec ls
# find: missing argument to '-exec'

\; 是命令结尾标记。或者用 +。

坑 6:含空格的文件名

find . -name "*.log" | xargs rm
# 文件 "a b.log" → xargs 切成 a 和 b.log

-print0 + xargs -0:

find . -name "*.log" -print0 | xargs -0 rm

或者用 -exec ... +:

find . -name "*.log" -exec rm {} +

坑 7:find . -name 大小写

find . -name "*.LOG"
# 找不到 a.log

加 -iname:

find . -iname "*.log"

坑 8:find 慢

find / -name file
# 慢死
  • 路径太大 → 缩小起点
  • 没 -prune 排除大目录
  • 进了 NFS / sshfs / 网络存储

加 -xdev 限制单文件系统、用 -prune 排除噪音目录、或换用 locate(基于索引):

locate file                                       # 查 mlocate 索引(不是实时)
updatedb                                          # 重建索引(cron 每天自动)

但 locate 索引可能 stale,不显示新文件。

坑 9:-mtime 和 -daystart 行为

find . -mtime +0                                  # 严格大于 0 天 = 24 小时以上
find . -mtime 0                                    # 0-24 小时
find . -mtime -1                                    # 同 -mtime 0

-mtime +0 是常被误解为"今天"——其实是"超过 24 小时"。

坑 10:find . -delete -empty 顺序问题

find . -type d -empty -delete
# 先删空目录、删完之后某些目录变空 → 但 find 不会重复扫描

要彻底删空目录:

find . -type d -empty -delete                     # 跑一次
find . -type d -empty -delete                     # 再跑一次
# 或者循环到没变化

替代 / 互补

工具特点
find经典、最通用
fd现代替代、快、默认遵守 .gitignore
locate / mlocate基于索引、快、但可能 stale
rg --filesripgrep 列出文件(含 gitignore 尊重)
tree树形看目录结构

K8s 节点 / 远端服务器 find 永远在,学好。


关联命令

  • xargs —— find ... | xargs 黄金组合
  • grep —— find ... -exec grep 找内容
  • lsblk —— find 找文件、lsblk 看盘
  • du —— du -sh 看目录总大小(详见 lsblk.md)
  • locate —— 用索引的快速查找(备用)
  • fd —— find 的现代替代
在 GitHub 上编辑此页