代码之家  ›  专栏  ›  技术社区  ›  Eric Lilja

如果找到匹配项,则停止find命令的递归

  •  2
  • Eric Lilja  · 技术社区  · 6 年前

    使用gnu findutils,我需要在目录树中搜索某个文件。如果为给定分支找到了该文件,我希望防止find进一步递归到分支中。假设我想找到文件foo,这是我的目录树:

    ├── a
    │   ├── a1
    │   │   └── foo
    │   └── foo
    ├── b
    └── c
        └── foo
    

    考虑到我正在搜索上面的树,我想找到a/foo和c/foo。但是,我不想找到a/a1/foo,因为我已经在a1的父目录中找到foo。 似乎我应该使用-prune标志来查找命令,我找到了这个链接 https://unix.stackexchange.com/questions/24557/how-do-i-stop-a-find-from-descending-into-found-directories 例如,但我不能让它工作。我的尝试包括:

    $ find -name foo -type f -prune
    ./a/a1/foo <- Unwanted hit
    ./a/foo
    ./c/foo
    

    $ find -name foo -type f -prune -exec find ../foo -type f {} \;
    find: paths must precede expression: ./a/a1/foo
    Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
    find: paths must precede expression: ./a/foo
    Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
    find: paths must precede expression: ./c/foo
    Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
    
    2 回复  |  直到 6 年前
        1
  •  6
  •   gniourf_gniourf    6 年前

    这将打印包含 foo ,并且不会在其子目录中重复出现:

    find -type d -exec test -f {}/foo \; -print -prune
    

    的行为 {}/foo is explicitly left undefined by POSIX :

    如果一个实用程序的名称或参数字符串包含两个字符“”,而不仅仅是两个字符“”,那么将定义find是替换这两个字符还是不更改地使用字符串。

    但与GNU的合作与预期一致 find (你在问题上加了标签 )正如Kamil Cuk在评论中正确建议的那样,如果您使用的是非GNU 找到 或者,如果您想要更便携的解决方案,请使用:

    find -type d -exec sh -c 'test -f "$1"/foo' -- {} \; -print -prune
    
        2
  •  2
  •   Nahuel Fouilleul    6 年前

    用“发现”很难做到 -prune 因为它在目录上工作,而find的基本条件是超过当前文件。

    另一种选择是用bash编程,使用递归函数,基本上

    rec_run() {
        local file
        for file in "${1:-.}"/*; do
            # to filter 'file=*' when no match is found
            if [[ ! -e $file ]]; then
                continue
            fi
    
            # do something with file
            echo "$file"
    
            # to filter known hard links
            if [[ $file = */. ]] || [[ $file = */.. ]]; then
                continue
            fi
    
            # if is a directory recursive call
            if [[ -d $file ]]; then
                rec_run "$file";
            fi
        done
    }
    

    更换零件 # do something 具有

        if [[ -f $file/foo ]]; then
            echo "$file/foo"
            continue
        fi
    

    在这里 foo 是硬编码的,但可以作为第二个函数参数传递

    注释 ${1:-.} 将第一个参数作为根目录,或 . 如果不通过

    推荐文章
    Sheldon  ·  缺少-exec的参数
    8 年前