4

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

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

鉴于我正在搜索上面的树,我想找到 a/foo 和 c/foo。但是,我不想找到 a/a1/foo,因为我已经在 a1 的父目录中找到了 foo。看来我应该在 find 命令中使用 -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]
4

2 回答 2

8

这将打印包含 的目录foo,并且不会在其子目录中递归:

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

{}/foo POSIX 明确未定义for 的行为:

如果实用程序名称或参数字符串包含两个字符“{}”,而不仅仅是两个字符“{}”,则由实现定义 find 是替换这两个字符还是直接使用字符串。

但可以按预期使用 GNU (并且您使用find标记了问题)。正如 Kamil Cuk 在评论中正确建议的那样,如果您使用的是非 GNU或想要更便携的解决方案,请使用:find

find -type d -exec sh -c 'test -f "$1"/foo' -- {} \; -print -prune
于 2019-02-07T18:00:30.657 回答
2

它不能用 find 轻松完成,-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:-.}是将第一个参数作为根目录或者.如果没有传递

于 2019-02-08T08:29:16.593 回答