使用 GNU findutils,我需要在目录树中搜索某个文件。如果已找到给定分支的文件,我想防止查找进一步递归到分支中。假设我想找到文件 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]
打印包含 foo
的目录,并且不会在其子目录中递归:
find -type d -exec test -f {}/foo ; -print -prune
POSIX 明确未定义{}/foo
的行为:
如果utility_name或参数字符串包含两个字符"{}",而不仅仅是两个字符"{}",则 find 是替换这两个字符还是使用字符串而不更改,则由实现定义。
但在 GNU find
上按预期工作(并且您用 GNU-findutils 标记了问题(。正如 Kamil Cuk 在评论中正确建议的那样,如果您使用的是非 GNU find
或者您想要一个更便携的解决方案,请使用:
find -type d -exec sh -c 'test -f "$1"/foo' -- {} ; -print -prune
它不能轻易地用查找-prune
完成,因为它适用于目录并且查找的基本条件是在当前文件上。
另一种方法是以编程方式使用 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:-.}
是将第一个参数作为根目录,如果未传递,则.