find 的 -prune 通过跳过匹配目录及其全部子内容来高效排除子目录,需配合 -type d 和 -o 使用,且必须置于逻辑表达式前分支;排除多个目录须用转义括号分组,按路径排除应改用 -path。

用 find 的 -prune 排除特定子目录,核心是利用它“跳过整个目录树”的行为,比单纯用 ! -path 更高效——因为 -prune 会让 find 完全不进入被匹配的目录,节省遍历开销。
理解 -prune 的执行逻辑
-prune 是一个动作(action),不是测试条件。它只对目录生效,且必须配合 -type d 使用;当某个目录被 -prune 匹配后,find 就不再递归进入该目录及其所有子内容,直接跳过。
关键点在于:它必须放在逻辑表达式的“前面分支”里,并用 -o(OR)连接后续操作,否则会被短路忽略。
排除单个目录的标准写法
例如,从当前目录查找所有 .log 文件,但跳过 logs/ 目录:
find . -name "logs" -prune -o -name "*.log" -print
-
-name "logs"先匹配名为logs的目录(注意:只匹配 basename,不关心路径层级) -
-prune立即跳过该目录及其全部子内容 -
-o表示“否则”,后面的部分才对未被 prune 的路径生效 -
-name "*.log" -print查找并打印其余路径下的.log文件
排除多个目录的写法
要排除 logs/ 和 cache/,不能简单叠加两个 -prune,而要用括号分组(注意 shell 中括号需转义):
find . \( -name "logs" -o -name "cache" \) -prune -o -name "*.conf" -print
-
\( ... \)把多个-name条件括起来,表示“匹配任一即可” - 只要当前路径 basename 是
logs或cache,就执行-prune -
-o后面的规则只作用于未被 prune 的路径
如果想按完整路径排除(比如只排除顶层的 ./logs,不碰 ./src/logs),可改用 -path 测试:
find . \( -path "./logs" -o -path "./temp" \) -prune -o -type f -print
常见错误与注意事项
以下写法容易出错,需避免:
- 漏掉
-o:如find . -name "logs" -prune -name "*.txt"→-prune后没分支,-name "*.txt"永远不会执行 - 括号没转义:
find . (-name a -o -name b) -prune会报语法错误,必须写成\( -name a -o -name b \) - 对文件用
-prune:-prune对非目录无效,也不报错,但起不到排除作用 - 顺序颠倒:把
-prune放在-o后面,逻辑就反了
实际使用时,建议先加 -print 或 -ls 验证哪些路径被纳入、哪些被跳过,再叠加其他动作。











