编程与开发 · 第 11 期

find 实战,-exec 与 -delete 的坑

删一万个文件,-exec 起一万个进程,-delete 一个都不起

find 看着简单,-exec 和 -delete 都能删文件,但坑天差地别:-exec 每个文件起一个进程,删一万个文件起一万个 rm;-delete 不能删非空目录,遇到子目录直接跳过。还有 -exec 末尾分号和加号的区别、xargs 的空格坑。选错命令,要么慢死,要么删不干净。
⏱ 约 9 分钟 🎯 用 find 删过文件但没踩过坑的人 📦 源:linux-command §4

01一个数字:-exec 删一万个文件,起一万个进程

同样删一万个 .log 文件,三种写法天差地别:

慢死:find . -name "*.log" -exec rm {} \; # 起 10000 个 rm
较快:find . -name "*.log" -exec rm {} + # 几个 rm,批量传参
最快:find . -name "*.log" -delete # 0 个进程,find 自己删

区别在 \; 和 +:分号是"每个文件起一次命令",一万个文件一万个 rm 进程,光 fork 就几十秒;加号是"攒一批文件一起传给一次命令",像 xargs 一样批量,几个 rm 搞定。而 -delete 干脆不 fork 任何外部命令,find 自己用 unlink 系统调用删,最快也最省。所以能 -delete 就 -delete,要 -exec 一定用 + 不用 \;。

-exec 用分号是一万次 fork,
用加号是几次。
灏天文库 · 编程与开发 P.33

02find 命令闯关:拼出正确的 find

下面三个任务,从备选词里点选 token 拼出正确的 find 命令。拼对了会告诉你为什么对,拼错了会告诉你踩了哪个坑。

🧩 find 命令闯关
点备选词填进命令槽,点槽里的词移除。三关递进。
← 拼好后点检查

03-delete 的暗坑:删不掉非空目录

-delete 快,但它本质是先 depth-first 遍历再 unlink。问题:如果目录非空,unlink 目录会失败(Linux 不允许删非空目录)。所以 find . -delete 遇到嵌套目录时,如果子目录里还有文件没被删,就会跳过那个目录,留下空壳。

解法是用 -depth(先访问子再访问父)配合,或者干脆用 -exec rm -rf {} + 让 rm 自己递归删。但 rm -rf 又危险——它不问青红皂白递归删,路径拼错就删错。这就是 find 的两难:-delete 安全但删不干净,rm -rf 干净但危险。工程上的稳妥写法是先 find ... -print 看一遍要删什么,确认无误再换 -delete。

-delete 删不掉非空目录,
rm -rf 删得掉但危险。
灏天文库 · 编程与开发 P.34

04xargs 的空格坑:文件名带空格就炸

很多人爱用 find ... | xargs rm,但文件名带空格就炸——xargs 默认按空格切,"my file.txt" 会被切成 "my" 和 "file.txt" 两个参数,rm 删两个不存在的文件。

解法是 find -print0 | xargs -0 rm:-print0 用 null 分隔文件名,-0 让 xargs 按 null 切,空格、换行都不怕。这是 find+xargs 的"安全模式",生产环境必须这么写。同理 -exec ... + 也是安全的(它内部用 null 分隔),所以"安全 + 批量"的写法是 -exec rm {} + 或 -print0 | xargs -0,两者都行,别用 \; 和裸 xargs。

记住这条口诀:分号慢、加号快、-delete 最快但删不净;xargs 怕空格,-print0 配 -0 才安全。能背下这条,find 的坑你踩过 80% 了。

05带走这套清单

✅ find 删除 6 条可执行规则

  1. -exec \; 每个文件起一个进程,删一万个起一万个 rm,慢死。
  2. -exec + 攒一批传给一次命令,快几个数量级,优先用 +。
  3. -delete 不 fork 外部命令,最快,但删不掉非空目录。
  4. 删嵌套目录用 -exec rm -rf {} +,但 rm -rf 危险,路径要核对。
  5. find+xargs 怕空格:必须 -print0 | xargs -0,否则文件名带空格就炸。
  6. 生产习惯:先 -print 看一遍,确认无误再换 -delete / -exec rm。
分号慢、加号快、delete 最快,
print0 配 0 才安全。
灏天文库 · 编程与开发 P.35