在深度优先遍历中限制find命令的结果

时间:2011-12-02 23:53:58

标签: find sh

我需要编写一个脚本来查找与命名模式匹配的所有文件,但是当我找到匹配项时,我不想再深入到任何子目录。我不知道脚本何时运行,可以找到哪些深度匹配。

一个例子可能有所帮助。如果我使用这样的find来查找我的Subversion目录:

find . -name .svn

结果如下:

./java/.svn
./java/com/.svn
./java/com/squeakysand/.svn
./java/com/squeakysand/taglib/.svn
./java/com/squeakysand/taglib/dev/.svn
./java/com/squeakysand/taglib/logging/.svn
./java/com/squeakysand/taglib/text/.svn
./java/com/squeakysand/taglib/util/.svn
./resources/.svn

但我真正想要这个特殊例子的结果只是第一个结果和最后一个结果。换句话说,一旦在.svn目录中找到java目录,我就不想在java目录下进一步搜索(如com本例中的目录)。但是,我确实希望结果在resources目录中,因为它不在java目录下。但是,与java目录一样,现在我在.svn目录下找到了resources目录,我想停止在resources目录下进一步搜索。

基本上我想做一个深度优先搜索匹配,当我找到一个匹配时,不要再往那条路走。

有没有办法使用find来执行此操作,还是有其他命令,或者可能是命令的组合?

3 个答案:

答案 0 :(得分:0)

试试这个

{
cat -<<EOS
./java/.svn
./java/com/.svn
./java/com/squeakysand/.svn
./java/com/squeakysand/taglib/.svn
./java/com/squeakysand/taglib/dev/.svn
./java/com/squeakysand/taglib/logging/.svn
./java/com/squeakysand/taglib/text/.svn
./java/com/squeakysand/taglib/util/.svn
./resources/.svn
./resources/com/.svn
EOS
} |sed 's@/@ @g' \
  | sort\
  | awk '{if (prev == $2) {prev=$2} else {prev=$2; gsub(" ", "/", $0);print $0}}'

# output
./java/.svn
./resources/.svn

请注意这个示例sed如何用空格替换所有'/'字符,最后用gsub(..)替换它们。尽可能在路径中有空格,你可能想要使用不同的char进行替换,但几乎任何char都是合法的unix文件名,所以如果你有一个完全开放的环境,那你就必须看看你的输出以确保它有意义。

我希望这会有所帮助。

答案 1 :(得分:0)

您需要将find测试与-prune结合使用。如果我更正,find没有你需要内置的测试。请考虑以下bash脚本,testprefix.sh :(使用基本原理,不适用于sh

#!/bin/bash
# Test if "$2" is a prefix of "$1"

test x"${1:0:${#2}}" = x"$2"

使用此脚本,您可以像这样调用find:

<击>     找 。 -name .svn(-exec ./testprefix.sh {} ./java/com/ \; -prune)-print

修改

find . -name .svn \( -exec ./testprefix.sh {} ./java/com \; -prune \) -or -print

(或者将-print替换为您想对优质文件采取的任何操作)

在这种情况下,括号\(\)是不必要的,但要更清楚。

答案 2 :(得分:0)

我相信find's man page几乎完全符合您的需求,它只是扩展到.gitCVS个子目录。复制&amp;粘贴在这里稍作修改:

find . -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS \; -print -prune
  

假设项目的以下目录结构及其关联的SCM管理目录:

./project1/CVS
./gnu/project2/.svn
./gnu/project3/.svn
./gnu/project3/src/.svn
./project4/.git
  

在这个例子中,-prune防止不必要的下降到已经发现的目录(例如我们不搜索project3 / src,因为我们已经找到了project3 / .svn),但是确保找到了兄弟目录(project2和project3) 。