【问题标题】:How to skip multiple directories when doing a find查找时如何跳过多个目录
【发布时间】:2017-12-13 17:59:54
【问题描述】:

我编写了一个查找函数,它在给定路径中的每个文件中搜索字符串,同时跳过我不想搜索的目录名称列表。我已将此脚本放在我的 .bashrc 文件中,以便像这样调用:

findTEXTinFILES /path/to/search 'text-to-find'

查找部分效果很好,它为搜索文本着色,使其在视觉上脱颖而出!但我无法让它跳过使用 -prune 列出的目录。我已经阅读了所有我能找到的帖子,但没有一个对我有用。我尝试了多种变体,但没有运气。所以我有几个问题:

  • 如何跳过多个目录?
  • 如何跳过仅包含部分名称的目录,例如以“--”或“wp-”开头的目录?
  • 能否在同一个脚本中混合使用 -name-path 条件?
  • 我还有什么遗漏的吗?

我的服务器是带有 bash shell 的 CENTOS 6.9 virtuozzo。

function findTEXTinFILES {

find "$1" ! \( -name .bash_history -prune \
    -o ! -path tmp -prune \
    -o ! -path short -prune \
    -o ! -path "*/_not_used/*" -prune \
    -o ! -path backups -prune \
    -o ! -path temp_logs -prune \
    -o ! -name .cpan -prune \
    -o ! -name .cpobjcache -prune \
    -o ! -path files_to_compare -prune \
    -o ! -path logs -prune \
    -o ! -path mail -prune  \
    -o ! -path old -prune \
    -o ! -path '--*' -prune \
    -o ! -path 'wp-*' -prune \
    -o ! -path '*copy*' -prune \) \
    -o -name "*" \
    -exec grep $2 -I --color -Hn '$3' '{}' 2>/dev/null \;
}

【问题讨论】:

    标签: linux text grep directory find


    【解决方案1】:

    find expression 主要由 testsactions 以及 operators 组成。它以标准的短路方式进行评估——这意味着一旦知道结果就会停止评估,而无需评估所有部分(例如,true or anything 被评估为true)。

    现在请注意,-prune 是一个始终返回 true 的操作。它可以作用于任何测试的结果。另请注意,默认运算符为-a)。

    因此,最简单的修剪示例,打印除某个路径下的文件(例如您的示例中的 wp-*)之外的所有文件,如下所示:

    find . -path './wp-*' -prune -o -print
    

    对于匹配以./wp-开头的路径的文件,执行剪枝操作,即结果为true,可以忽略OR运算符的右侧部分(即不打印文件)。注意这里-path匹配相对路径,在本例中以.为根,所以我们必须写./wp-*而不是wp-*

    要修剪两条路径,只需扩展:

    find . -path './wp-*' -prune -o -path ./logs -prune -o -print
    

    这里:如果第一个修剪动作没有被执行(结果false),那么有机会给第二个,如果这两个都没有修剪(结果false),那么-print动作被执行。如果任何-prune 被评估,-print 就没有机会。

    将此应用于您的案例:

    find "$1" -name .bash_history -prune \
        -o -path "$1/tmp" -prune \
        -o -path "$1/short" -prune \
        -o -path "$1/*/_not_used/*" -prune \
        -o -path "$1/backups" -prune \
        -o -path "$1/temp_logs" -prune \
        -o -name "$1/.cpan" -prune \
        -o -name "$1/.cpobjcache" -prune \
        -o -path "$1/files_to_compare" -prune \
        -o -path "$1/logs" -prune \
        -o -path "$1/mail" -prune  \
        -o -path "$1/old" -prune \
        -o -path "$1/--*" -prune \
        -o -path "$1/wp-*" -prune \
        -o -path "$1/*copy*" -prune \
        -exec grep $2 -I --color -Hn '$3' '{}' 2>/dev/null \;
    

    为避免编写依赖于 $1 的路径,您可以 cd "$1" 并使用 f.e. find . ... -path ./logs ....

    【讨论】:

    • 很好的答案。谢谢! +1用于短路解释。看起来添加当前路径($1)使其工作。我以前没有看到过这样的解释。不过,仍有一些情况下它不起作用……为了测试,我创建了新目录并添加了要搜索的文件,但是脚本没有拾取它们,尽管它们是裸露的find。奇怪的。我还尝试通过添加 -o -name "$1/*copy*" -prune \ 来跳过名称中包含“复制”一词的文件,但它们仍在搜索中返回。
    • 谢谢,不客气! (如果它解决了您的问题,请随时 accept it :-))。关于您的$1/*copy* 搜索——您不能在-name 测试中指定路径(仅在-path 中)。要修剪包含单词 copy 的路径,请使用:-name '*copy*' -prune
    猜你喜欢
    • 2014-04-08
    • 1970-01-01
    • 2022-06-11
    • 2017-05-14
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多