排除 find 命令中除一个特定路径之外的所有子目录

排除 find 命令中除一个特定路径之外的所有子目录

我使用find命令在当前子目录中搜索具有给定扩展名的所有文件,忽略某些目录路径:

find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" \) -prune -o -name "*.ext"

这工作得很好,但现在我想忽略除了其中一个精确子目录之外的另一条路径。如何在不列出所有要忽略的子目录的情况下执行此操作?

例如,如果我有以下文件夹树:

*/base/pathToIgnore1
*/base/subdir/requiredPath
*/base/subdir/pathToIgnore2
*/base/subdir/pathToIgnore3
*/base/pathToIgnore4

如何编写find命令忽略base除路径之外的所有子目录*/base/subdir/requiredPath

我尝试过类似的东西

find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \( -wholename "*/base" -a ! -wholename "*/base/subdir/requiredPath" \) \) -prune -o -name "*.ext"

但它不起作用,所有base子目录都被忽略。

答案1

find -L . \
  \( -type d \
    \( -path "*/ignore" -o -path "*/indeed" -o \
      \( -path "*/subdir/*" ! -path "*/subdir/save" \
      \) \
    \) \
  \) \
  -prune -o -print

如果你想要额外的过滤器(比如-name "*.ext"),你必须把它放在前面-print。最后一部分看起来像这样

  -prune -o \( -name "*.ext" \) -print

请注意,我更改了名称以便于书写和阅读。以 开头的名称i将被忽略。s将显示以 开头的名称。以 结尾的名称file是文件。

我的树看起来像这样:

$ find -printf "%y %p\n"
d .
d ./base
d ./base/subdir
d ./base/subdir/inform
f ./base/subdir/inform/imagefile
d ./base/subdir/isolate
f ./base/subdir/isolate/individualfile
f ./base/subdir/whatwhatinthefile
d ./base/subdir/save
f ./base/subdir/save/soundfile
f ./base/superfile
d ./base/indeed
f ./base/indeed/itemfile
d ./base/show
f ./base/show/startfile
d ./base/ignore
f ./base/ignore/importantfile

上述命令的输出:

.
./base
./base/subdir
./base/subdir/whatwhatinthefile
./base/subdir/save
./base/subdir/save/soundfile
./base/superfile
./base/show
./base/show/startfile

请注意,whatwhatinthefilebase/subdir.如果您不想要这些文件,base/subdir那么您必须明确排除它们。我尝试过,但命令行变得太难看了。

根据您的用例,定义如下 shell 函数可能会更容易:

contrivedfind() {
  find -L . \
    \( -type d \
      \( -path "*/ignore" -o -path "*/indeed" -o -path "*/subdir" \
      \) \
    \) \
    -prune -o -print
  find -L ./base/subdir/save
}

现在输出是:

.
./base
./base/superfile
./base/show
./base/show/startfile
./base/subdir/save
./base/subdir/save/soundfile

与以前唯一不同的是缺少./base/subdir条目。但我认为这对你来说并不重要,因为你无论如何都想过滤文件。

和以前一样,您必须-print在第一个之前放置任何额外的过滤器find,这次也在第二个的末尾放置find

答案2

你必须防止它*/base本身被匹配:

编辑1:

find -L . -type d \
  \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \
  \( -wholename "*/base/*" -a \
  \( ! -wholename "*/base/subdir" -a ! -wholename "*/base/subdir/*" \) \) -o \
  \( -wholename "*/base/subdir/*" -a \
  \( ! -wholename "*/base/subdir/requiredPath" -a ! -wholename "*/base/subdir/requiredPath/*" \) \) \) \
  -prune -o -print

这有点挑剔:它可以防止意外匹配subdir2可能不存在的目录。但你永远不知道...:-)

相关内容