rm .ext不能递归删除子目录文件,仅匹配当前目录;rm -r .log会误删同名目录而非.log文件;安全递归删除需用find . -name "*.ext" -type f -delete或find ... -exec rm -f {} \;。

直接用 rm *.ext 最快,但只删当前目录;要递归删子目录里的,必须用 find —— 否则会漏掉、误删,甚至触发 shell 报错。
rm *.ext 能不能直接递归删除?
不能。rm 本身不支持递归匹配子目录下的同名后缀文件。写成 rm -r *.log 看似递归,实际是让 rm 递归删除所有叫 *.log 的**目录**(如果真存在这种名字的目录),而不是删所有 .log 文件。这是常见误解。
-
rm *.log:只展开当前目录下匹配的文件,不进子目录 -
rm -r *.log:先 glob 展开当前目录匹配项,再对每个结果尝试递归删除——若结果是文件,-r无效;若是目录,才真递归删目录 - 一旦当前目录没有
.log文件,shell 就报错rm: cannot remove '*.log': No such file or directory,命令中断
find -name "*.ext" -delete 安全吗?
基本安全,但有前提:-delete 是 find 的非 POSIX 扩展选项,GNU find(Linux 默认)支持,macOS 的 find 不支持,会报错 find: -delete: unknown primary or operator。
- 推荐写法:
find . -name "*.log" -type f -delete -
-type f很关键:排除同名目录,避免误删目录本身(比如真有个叫access.log的空目录) - 执行前可先试运行:
find . -name "*.log" -type f,确认列表无误再加-delete - 如果系统不支持
-delete(如旧版 BusyBox 或 macOS),改用-exec rm -f {} \;
为什么 -exec rm -f {} \; 里必须有空格和反斜杠?
因为 shell 会先解析 \;,把它当做一个字面分号传给 find,否则 ; 被 shell 当作命令分隔符,导致 find 只执行到 {} 就结束了,后面 rm 变成独立命令、拿不到文件名。
- 正确:
find . -name "*.tmp" -type f -exec rm -f {} \; - 错误:
find . -name "*.tmp" -type f -exec rm -f {} ;(shell 截断) - 错误:
find . -name "*.tmp" -type f -exec rm -f {} \(缺分号,语法错误) - 也可用引号:
find . -name "*.tmp" -type f -exec rm -f {} ';',效果等价 -
{}和\;之间必须有空格,否则find识别不了动作边界
批量删多个后缀,比如 .log 和 .tmp?
别写 rm *.log *.tmp —— 如果任一模式没匹配到,shell 就原样传给 rm,导致删错名字为 *.log 的文件(字面匹配)。
- 安全做法:用
find多条件组合:find . \( -name "*.log" -o -name "*.tmp" \) -type f -delete - 注意括号要转义:
\(和\),否则 shell 会试图执行子 shell - 或分两次执行,更清晰:
find . -name "*.log" -type f -delete && find . -name "*.tmp" -type f -delete - 如果路径含空格或特殊字符,
-exec比xargs更可靠;xargs rm -f在文件名含换行时可能出错
最易被忽略的是 -type f —— 没它,遇到同名目录就不是删文件,而是删整个目录。还有就是 rm 的 glob 不进子目录,这点很多人凭直觉写错,一跑就删偏。


















