find 的 prune 的 -path 不带通配符

find 的 prune 的 -path 不带通配符

我想从查找搜索树中排除一个目录。.aaa是当前目录中的隐藏子目录。我想排除其名称中aaa_rc_bbb, xxx_rc_xxx包含的更多子目录。rc但它仍然没有忽略并给我包含rc子目录的结果。就好像*rc*通配符不起作用一样。

find -L /students/projects/myname/ -name .aaa -prune -o -path */*/class_project/*/*/pikachu/*/*/*rc*/ -prune -o -path */*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt | head -n50 | xargs ls

另外,我想 find 仅在此路径中搜索:*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt

请帮我。我做错了什么吗?

答案1

第一个问题是您有未加引号的 glob ( *)。所有这些路径都应该用单引号引起来,例如'*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt'。这可以防止 shell 在通配符传递到 之前对其进行扩展find

接下来,您需要-prune子表达式出现在主搜索子表达式之前。顺便说一句,您可以将所有名称组合成一个复合表达式,如下所示-prune

find \( \( -name '*foo*' -o -name '*bar*' \) -a -prune \) -o \( -name baz -a -print \)

这意味着我想查找指定的文件,同时排除包含其名称或在其名称中的baz任何文件/目录。foobar

一些注意事项:

  • 我对 (AND) 运算符和括号很自由-a,因此没有歧义。
  • 括号的作用是改变优先级,就像大多数其他表达式类型一样,用 进行转义,\因此它们在传递给 之前不会被 shell 解释find
  • 我正在使用两个-name测试,但任何其他测试(例如-path)都可以位于第一个嵌套的括号中。与任何测试匹配的任何文件/目录都将被修剪,因此不会应用于下一个测试(在最后一组括号中)。
  • 明确动作以-print将其与-prune部分区分开来是个好主意。

为了清楚起见,让我们用更常见的表达风格重写它:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print)

甚至

if (name=='*foo*' OR name=='*bar*')
   prune
else if (name==bar)
   print
fi

现在给出正常的优先规则并且默认的布尔运算符是-a我们可以将示例简化为:

find \( -name '*foo*' -o -name '*bar*' \) -prune -o -name baz -print

find转向您的命令,为它发现的文件构建的路径永远不会以/字符结尾,因此-path '*/*/class_project/*/*/pikachu/*/*/*rc*/'永远不可能匹配。如果您想限制类型的文件,您需要删除该尾随/并可能添加-type d目录

另请注意,*/*作为模式匹配包含 的任何字符串/,也包含foo/bar/baz.在这里,您的路径都以 开头,/students/projects/myname/因此/in*/*是多余的,因为我们已经知道它/会在那里。

如果我正确地阅读了您的意图,那么您没有对第二个子表达式进行任何测试,即如果文件没有被修剪,您想要打印它。所以这导致

find -L /students/projects/myname/ \
  \( \
       -name .aaa \
    -o -path '*/class_project/*/*/pikachu/*/*/*rc*' \
    -o -path '*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt' \
  \) -prune \
  -o -print

答案2

您的-path模式以斜线结尾。find检查的路径名永远不会以斜线结尾,因此该模式永远不会匹配任何内容。

要修剪任何被调用的目录及其名称中.aaa包含的任何目录:rc

find -L /students/projects/myname \
    -type d '(' -name '.aaa' -o -name '*rc*' ')' -prune -o -print

仅查看路径*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt

find -L /students/projects/myname \
    -type d '(' -name '.aaa' -o -name '*rc*' ')' -prune -o \
    -path '*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt' -print

这假设bambi.txt位于

/students/projects/myname/*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt

请注意命令中模式的引用find。如果没有引号,shell 会在调用之前尝试将模式扩展为路径名列表find,这可能会导致混乱find,或者对于某些 shell 会导致错误。

相关内容