Linux 如何让 `find` 忽略 .svn 目录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2314643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get `find` to ignore .svn directories?
提问by John Kugelman
I often use the findcommand to search through source code, delete files, whatever. Annoyingly, because Subversion stores duplicates of each file in its .svn/text-base/directories my simple searches end up getting lots of duplicate results. For example, I want to recursively search for uintin multiple messages.hand messages.cppfiles:
我经常使用该find命令来搜索源代码、删除文件等等。令人讨厌的是,因为 Subversion 在其.svn/text-base/目录中存储了每个文件的重复项,所以我的简单搜索最终会得到很多重复的结果。例如,我想uint在多个messages.h和messages.cpp文件中递归搜索:
# 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;
How can I tell findto ignore the .svndirectories?
我怎么知道find要忽略.svn目录?
Update: If you upgrade your SVN client to version 1.7this is no longer an issue.
更新:如果您将 SVN 客户端升级到1.7 版,这不再是问题。
A key feature of the changes introduced in Subversion 1.7 is the centralization of working copy metadata storage into a single location. Instead of a
.svndirectory in every directory in the working copy, Subversion 1.7 working copies have just one.svndirectory—in the root of the working copy. This directory includes (among other things) an SQLite-backed database which contains all of the metadata Subversion needs for that working copy.
Subversion 1.7 中引入的更改的一个关键特性是将工作副本元数据存储集中到一个位置。
.svnSubversion 1.7 工作副本只有一个.svn目录——工作副本的根目录,而不是在工作副本的每个目录中都有一个目录。该目录包括(除其他外)一个 SQLite 支持的数据库,其中包含 Subversion 对该工作副本所需的所有元数据。
采纳答案by Brian Agnew
回答by John Kugelman
Create a script called ~/bin/svnfind:
创建一个名为 的脚本~/bin/svnfind:
#!/bin/bash
#
# Attempts to behave identically to a plain `find' command while ignoring .svn/
# directories.
OPTIONS=()
PATHS=()
EXPR=()
while [[ =~ ^-[HLP]+ ]]; do
OPTIONS+=("")
shift
done
while [[ $# -gt 0 ]] && ! [[ =~ '^[-(),!]' ]]; do
PATHS+=("")
shift
done
# If user's expression contains no action then we'll add the normally-implied
# `-print'.
ACTION=-print
while [[ $# -gt 0 ]]; do
case "" in
-delete|-exec|-execdir|-fls|-fprint|-fprint0|-fprintf|-ok|-print|-okdir|-print0|-printf|-prune|-quit|-ls)
ACTION=;;
esac
EXPR+=("")
shift
done
if [[ ${#EXPR} -eq 0 ]]; then
EXPR=(-true)
fi
exec -a "$(basename "# svnfind -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) {
./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;
")" find "${OPTIONS[@]}" "${PATHS[@]}" -name .svn -type d -prune -o '(' "${EXPR[@]}" ')' $ACTION
This script behaves identically to a plain findcommand but it prunes out .svndirectories. Otherwise the behavior is identical.
此脚本的行为与普通find命令相同,但它会删除.svn目录。否则行为是相同的。
Example:
例子:
find . -path '*/.svn*' -prune -o -print
回答by Kaleb Pederson
As follows:
如下:
find . -name .svn -a -type d -prune -o -print
Or, alternatively based on a directory and not a path prefix:
或者,或者基于目录而不是路径前缀:
find . ! -regex ".*[/]\.svn[/]?.*"
回答by ghostdog74
GNU find
GNU 查找
findrepo uint 'messages.*'
回答by pixelbeat
回答by me.
find . | grep -v \.svn
find . | grep -v \.svn
回答by Vijay
Why dont you pipe your command with grep which is easily understandable:
为什么不使用易于理解的 grep 来管理您的命令:
export GREP_OPTIONS="--binary-files=without-match --color=auto --devices=skip --exclude-dir=CVS --exclude-dir=.libs --exclude-dir=.deps --exclude-dir=.svn"
回答by leedm777
回答by vladr
Just thought I'd add a simple alternativeto Kaleb's and others' posts (which detailed the use of the find -pruneoption, ack, repofindcommands etc.) which is particularly applicable to the usage you have described in the question(and any other similar usages):
只是想我会为 Kaleb 和其他人的帖子添加一个简单的替代方案(其中详细说明了find -prune选项ack、repofind命令等的使用),这特别适用于您在问题中描述的用法(以及任何其他类似用法):
For performance, you should always try to use
find ... -exec grep ... +(thanks Kenji for pointing this out) orfind ... | xargs egrep ...(portable) orfind ... -print0 | xargs -0 egrep ...(GNU; works on filenames containing spaces) insteadoffind ... -exec grep ... \;.The
find ... -exec ... +andfind | xargsform does not forkegrepfor each file, but rather for a bunch of files at a time, resulting in much faster execution.When using the
find | xargsform you can also usegrepto easily and quickly prune.svn(or any directories or regular expression), i.e.find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...(useful when you need something quick and can't be bothered to remember how to set upfind's-prunelogic.)The
find | grep | xargsapproach is similar to GNUfind's-regexoption (seeghostdog74's post), but is more portable (will also work on platforms where GNUfindis not available.)
出于性能考虑,你应该总是尝试使用
find ... -exec grep ... +(感谢贤治指出了这一点)或find ... | xargs egrep ...(便携式)或find ... -print0 | xargs -0 egrep ...(GNU;作品含有空格的文件名)来代替的find ... -exec grep ... \;。在
find ... -exec ... +和find | xargs形式不分叉egrep为每个文件,而是在一次一堆文件,从而导致更快的执行。使用
find | xargs表单时,您还可以使用grep它轻松快速地修剪.svn(或任何目录或正则表达式),即find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...(当您需要快速处理某些事情并且不费心去记住如何设置find的-prune逻辑时很有用。)该
find | grep | xargs方法类似于 GNUfind的-regex选项(请参阅ghostdog74的帖子),但更具可移植性(也适用于 GNUfind不可用的平台。)
回答by Ronny Brendel
I use grep for this purpose. Put this in your ~/.bashrc
为此,我使用 grep。把它放在你的 ~/.bashrc 中
##代码##grep automatically uses these options on invocation
grep 在调用时自动使用这些选项

