我经常使用find命令来搜索源代码、删除文件等等。令人烦恼的是,由于Subversion在.svn/text-base/目录中存储了每个文件的副本,我的简单搜索最终会得到大量重复的结果。例如,我想在多个messages.h和messages.cpp文件中递归搜索uint:

# find -name 'messages.*' -exec grep -Iw uint {} +
./messages.cpp:            Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./messages.cpp:    Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./messages.cpp:                Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./messages.cpp:            Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./messages.cpp:            Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./messages.cpp:        Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./messages.cpp:        for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./.svn/text-base/messages.cpp.svn-base:            Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./.svn/text-base/messages.cpp.svn-base:    Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base:                Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base:            Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base:            Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base:        Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base:        for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./virus/messages.cpp:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/messages.cpp:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/messages.h:    void _progress(const std::string &fileName, uint scanCount);
./virus/messages.h:    ProgressMessage(const std::string &fileName, uint scanCount);
./virus/messages.h:    uint        _scanCount;
./virus/.svn/text-base/messages.cpp.svn-base:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.cpp.svn-base:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.h.svn-base:    void _progress(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base:    ProgressMessage(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base:    uint        _scanCount;

我怎么能告诉find忽略。svn目录?


更新:如果您将SVN客户端升级到1.7版本,这就不再是一个问题。

Subversion 1.7中引入的更改的一个关键特性是将工作副本元数据存储集中到单个位置。Subversion 1.7工作副本只有一个.svn目录,而不是在工作副本的每个目录中都有一个.svn目录——在工作副本的根目录。这个目录包括一个sqlite支持的数据库,其中包含Subversion工作副本所需的所有元数据。


当前回答

如果您这样做,请注意

找到。-type f -name 'messages.*'

那么,当整个表达式(-type f -name 'messages.*')为真时,-print将被隐含,因为没有'action'(如-exec)。

然而,为了停止降级到某些目录,您应该使用与这些目录匹配的任何内容,并在后面加上-prune(这是为了停止降级到目录);像这样:

找到。-type d -name '。svn的修剪

对于.svn目录,它的计算结果为True,我们可以在后面加上-o (OR)来使用布尔短路,在此之后,-o之后的内容仅在第一部分为False时进行检查,因此不是.svn目录。换句话说,如下:

找到。-type d -name '。Svn ' -prune -o -name '消息。*' -exec grep -Iw uint {}

将只计算正确的-o,即-name '消息。*' -exec grep -Iw uint{},用于不在.svn目录下的文件。

请注意,因为.svn可能总是一个目录(而不是例如一个文件),在这种情况下肯定不匹配name '消息。*',你可以省略类型d,这样做:

找到。- name”。Svn ' -prune -o -name '消息。*' -exec grep -Iw uint {}

最后,注意如果你省略了任何动作(-exec是一个动作),像这样说:

找到。- name”。Svn ' -prune -o -name '消息。*'

则-print操作是隐含的,但将应用于整个表达式,包括名称'。删除Svn ' -prune -o部分,从而打印所有. Svn目录以及'消息。*'文件,这可能不是你想要的。因此,当以这种方式使用-prune时,你总是应该在布尔表达式的右侧使用一个'action'。当这个动作正在打印时,你必须显式地添加它,像这样:

找到。- name”。Svn ' -prune -o -name '消息。*的安全性

其他回答

wcfind是一个查找包装器脚本,我使用它来自动删除.svn目录。

试试findrepo,它是find/grep的简单包装器,比ack快得多 在这种情况下,你可以这样使用它:

findrepo uint 'messages.*'

我通常再一次通过grep管道输出,删除.svn,在我的使用中它并不会慢很多。 典型的例子:

find -name 'messages.*' -exec grep -Iw uint {} + | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'

OR

find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'

GNU 查找

find .  ! -regex ".*[/]\.svn[/]?.*"

在源代码存储库中,我通常只想对文本文件进行操作。

第一行是所有文件,不包括CVS、SVN和GIT存储库文件。

第二行排除所有二进制文件。

find . -not \( -name .svn -prune -o -name .git -prune -o -name CVS -prune \) -type f -print0 | \
xargs -0 file -n | grep -v binary | cut -d ":" -f1