我想从查找搜索树中排除一个目录。.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/bambi.txt | head -n50 | xargs ls
。
另外,我想 find 仅在此路径中搜索:*/*/class_project/*/*/pikachu/*/*/bambi/bambi.txt
请帮我。我做错了什么吗?
答案1
第一个问题是您有未加引号的 glob ( *
)。所有这些路径都应该用单引号引起来,例如'*/*/class_project/*/*/pikachu/*/*/bambi/bambi.txt'
。这可以防止 shell 在通配符传递到 之前对其进行扩展find
。
接下来,您需要-prune
子表达式出现在主搜索子表达式之前。顺便说一句,您可以将所有名称组合成一个复合表达式,如下所示-prune
:
find \( \( -name '*foo*' -o -name '*bar*' \) -a -prune \) -o \( -name baz -a -print \)
这意味着我想查找指定的文件,同时排除包含其名称或在其名称中的baz
任何文件/目录。foo
bar
一些注意事项:
- 我对 (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/bambi.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/bambi.txt
:
find -L /students/projects/myname \
-type d '(' -name '.aaa' -o -name '*rc*' ')' -prune -o \
-path '*/*/class_project/*/*/pikachu/*/*/bambi/bambi.txt' -print
这假设bambi.txt
位于
/students/projects/myname/*/*/class_project/*/*/pikachu/*/*/bambi/bambi.txt
请注意命令中模式的引用find
。如果没有引号,shell 会在调用之前尝试将模式扩展为路径名列表find
,这可能会导致混乱find
,或者对于某些 shell 会导致错误。