Bash - 使用find命令排除子目录

时间:2015-04-20 13:44:03

标签: bash shell find

我使用find命令获取某些文件所在的文件夹列表。但由于某些子目录的权限被拒绝错误,我想排除某个子目录名称。 我已经尝试过这里找到的解决方案:

find /path/to/folders -path "*/noDuplicates" -prune -type f -name "fileName.txt"

find /path/to/folders ! -path "*/noDuplicates" -type f -name "fileName.txt"

这些命令的一些变体(例如路径名的变体)。 在第一种情况下它根本找不到文件夹,在第二种情况下我再次得到错误,所以我猜它仍然试图访问这个目录。有谁知道我做错了什么,或者有没有人为此做出不同的解决方案?

4 个答案:

答案 0 :(得分:3)

补充olivm's helpful answer并解决OP的困惑需要-o

  • -prune,因为每个find主要(动作或测试,在GNU中说),返回布尔,并且该布尔始终为{{1} } {/ strong>,如果是true
  • 如果没有明确的运算符,则原语与-prune-a)隐式关联,与其兄弟-and-o)执行短路< / em>布尔逻辑。
  • -or的优先级高于-a

有关所有-o概念的摘要,请参阅https://stackoverflow.com/a/29592349/45375

因此,接受的答案

find

等效于(括号用于使评估优先级明确):

find . -path ./ignored_directory -prune -o -name fileName.txt -print

由于短路适用,因此评估如下:

  • 匹配find . \( -path ./ignored_directory -a -prune \) \ -o \ \( -name fileName.txt -a -print \) 的输入路径会导致./ignored_directory被评估;由于-prune始终返回-prune,因此短路会阻止评估true运算符的侧;实际上,没有任何反应(输入路径被忽略)
  • 输入路径不匹配-o,立即 - 再次由于短路 - 继续评估./ignored_directory右侧侧:
    • 仅当输入路径的文件名部分与-o匹配时才评估fileName.txt。实际上,只打印文件名与-print匹配的输入路径。

修改:尽管我最初声称在此处,但fileName.txt-print的右侧需要-o;没有它,暗示 -print将适用于整个表达式,因此 打印 left - 手边比赛;请参阅下面的背景信息。


相比之下,让我们考虑错误地使用-o

find . -path ./ignored_directory -prune -name fileName.txt -print

这相当于:

find . -path ./ignored_directory -a -prune -a -name fileName.txt -a -print

这将打印已修剪的路径(也与-name过滤器匹配),因为-name-print原色(隐含地)与逻辑AND连接;
在这种特定情况下,由于./ignored_directory也不能匹配fileName.txt,因此没有打印,但如果-path的参数是 glob 可以获得输出。


关于 find 隐式使用-print 的一句话:

POSIX mandates如果find命令的表达式为WHOLE,则不包含

  • 输出生成原色,例如-print本身
  • 执行某些内容的初选,例如-exec-ok
  • (给出的示例原型对于find POSIX 规范是详尽无遗的,但实际的实现,如GNU find和BSD find添加其他产品,例如产生产出的-print0主要产品和正在执行的-execdir主要产品

-print隐式应用,就好像表达式被指定为:

\( expression \) -print

这很方便,因为它允许您编写find .等命令,而无需附加-print

但是,在某些情况下,需要明确的-print ,如下所示:

我们说在接受的答案结尾处我们没有指定-print

find . -path ./ignored_directory -prune -o -name fileName.txt

由于现在表达式中没有输出生成或执行主要内容,因此将其评估为:

find . \( -path ./ignored_directory -prune -o -name fileName.txt \) -print

这不会按预期工作,因为如果整个括号表达式的计算结果为true,它将打印路径,在这种情况下错误地包含已修剪的目录。

相比之下,通过将-print显式附加到-o分支,仅当-o表达式的右侧评估为true时才会打印路径;使用括号使逻辑更清晰:

find . -path ./ignored_directory -prune -o \( -name fileName.txt -print \)

相反,如果左侧是真的,则仅执行-prune,这不会产生任何输出(并且因为整体表达式包含-print-print未被隐式应用。)

答案 1 :(得分:1)

按照我之前的评论,这适用于我的Debian:

find . -path ./ignored_directory -prune -o -name fileName.txt -print

find /path/to/folder -path "*/ignored_directory" -prune -o -name fileName.txt -print

find /path/to/folder -name fileName.txt -not -path "*/ignored_directory/*"

差异很有争议here

答案 2 :(得分:1)

修改(添加了行为规范详情)

修剪查找

中的所有权限被拒绝的目录

使用gnufi​​nd。

规范行为详细信息 - 在此解决方案中,我们希望:

  1. 排除不可读的目录内容(修剪它们),
  2. 避免来自不可读的dierctory的“权限被拒绝”错误,
  3. 保留其他错误并返回状态,但
  4. 处理所有文件(即使是不可读的文件,如果我们可以阅读他们的名字)
  5. 基本设计模式是:

    find ...  \( -readable -o -prune \) ...
    

    实施例

    find /var/log/ \( -readable -o -prune \) -name "*.1" 
    

    \ {感谢} mklement0

答案 3 :(得分:-1)

问题在于find评估您传递给-path选项的表达式的方式。 相反,你应该尝试类似的东西:

find /path/to/folders ! -path "*noDuplicates*" -type f -name "fileName.txt"