在 find 命令中排除目录范围

Exclude range of directories in find command

我有一个名为 test 的目录,其中包含 0102、...31 等日期范围内的子文件夹。这所有子文件夹中都包含 .bz2 文件。我需要使用 find 命令搜索扩展名为 .bz2 的所有文件,但不包括特定范围的目录。我知道 find . -name ".bz2" -not -path "./01/*",但是如果我想跳过 10 个目录,写 -not -path "./01/*" 会很可怜。那么如何在 find 命令中跳过 01..19 子目录?

您可以在选项模式中使用通配符 -not -path:

find ./ -type f -name "*.bz2" -not -path "./0*/*" -not -path "./1*/*

这将排除所有以 0 或 1 开头的目录。甚至更好:

find ./ -type f -name "*.bz2" -not -path "./[01]*/*"

首先,您可以使用 -prune 而不是 -not -path 来帮助 find - 这甚至可以避免查看相关目录。

关于您的要点 - 您可以为您的示例构建一个通配符(数字 01 到 19):

find . -path './0[1-9]' -prune -o -path './1[0-9]' -prune -o -print

如果您的范围不太方便(例如 05 到 25),您可能希望将范围构建到 bash 变量中,然后将其插入到 find 命令中:

a=("-path ./"{05..25}" -prune -o")
find . ${a[*]} -print -prune

(您可能想 echo "${a[*]}"printf '%s\n' ${a[*]} 看看它是如何工作的)

对我来说,我发现 find 命令作为一个独立的工具有点麻烦。因此,我总是最终使用 find 的组合来进行递归文件搜索和 grep 来制作实际的 exculsion/inclusion 东西。最后,我将结果移交给第三个命令,该命令将执行操作,例如 rm 以删除文件。

我的通用命令看起来像这样:

find [root-path] | grep (-v)? -E "cond1|cond2|...|condN" | [action-performing-tool] 
  • 根路径是递归开始搜索的地方
  • 添加-v选项用于反转匹配结果
  • cond1 - condN,匹配的条件。当涉及 -v 时,这是匹配的条件。
  • 动作执行工具完成实际工作

例如,您想要删除所有匹配当前目录中某些条件的文件:

find . -not -name "\." | grep -v -E "cond1|cond2|cond3|...|condN" | xargs rm -rf

如你所见,我们是在当前目录中以点号为root-path:搜索,然后我们要反转匹配结果,因为我们要的是所有文件not 匹配我们的条件:最后我们将找到的所有文件传递给 rm 以便删除它们:我将 -rf 添加到 recursive/force 删除所有文件。我使用带有 -not -name "." 的 find 命令来排除通常由点指示的当前目录。

对于实际问题:假设我们有一个使用 .git 和 .metadata 目录的目录,我们想在搜索中排除它们:

find . -not -name "\." | grep -v -E ".git|.metadata" | [action-performing-tool]

希望对您有所帮助!

如果您想排除父目录下的子目录,那么这可能会有用:

例如-您有父目录 "ParentDir" 并且它有两个子目录 "Child1, Child2"。您只想从 "Chiled2" 读取文件并跳过 "Child1"。那么这将有所帮助。

find ./ParentDir ! -path "./ParentDir/Child1*" -name *.<extention>