How can I get `find` to ignore .svn directories?
我经常使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 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; |
我怎样才能告诉
更新:如果您将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
.svn directory in every directory in the working copy, Subversion 1.7 working copies have just one.svn directory—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.
为什么不只是
1 | find . -not -iwholename '*.svn*' |
-not谓词否定路径中任何位置具有.svn的所有内容。
所以在你的情况下
1 | find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \; |
如下:
1 | find . -path '*/.svn*' -prune -o -print |
或者,基于目录而不是路径前缀:
1 | find . -name .svn -a -type d -prune -o -print |
为了寻找,我建议你看看ACK?它是一个源代码感知的
要忽略
1 | find . -type f -not -path '*/\.*' |
但是,如果使用
git grep —专门设计的命令,用于在git存储库中搜索模式。ripgrep —默认情况下忽略.gitignore 中指定的隐藏文件和文件。
相关:如何在Linux上找到包含特定文本的所有文件?
以下是我对您的案例所做的:
1 | find . -path .svn -prune -o -name messages.* -exec grep -Iw uint {} + |
Emacs的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | find . \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path \*/MCVS \ -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path \*/.bzr \ -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{arch\} \) \ -prune -o \ \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name \*.bin -o -name \*.lbin \ -o -name \*.so -o -name \*.a -o -name \*.ln -o -name \*.blg \ -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name \*.glo \ -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm \ -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem \ -o -name \*.x86f -o -name \*.sparcf -o -name \*.fasl -o -name \*.ufsl \ -o -name \*.fsl -o -name \*.dxl -o -name \*.pfsl -o -name \*.dfsl \ -o -name \*.p64fsl -o -name \*.d64fsl -o -name \*.dx64fsl -o -name \*.lo \ -o -name \*.la -o -name \*.gmo -o -name \*.mo -o -name \*.toc \ -o -name \*.aux -o -name \*.cp -o -name \*.fn -o -name \*.ky \ -o -name \*.pg -o -name \*.tp -o -name \*.vr -o -name \*.cps \ -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name \*.tps \ -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) \ -prune -o \ -type f \( -name pattern \) -print0 \ | xargs -0 -e grep -i -nH -e regex |
它忽略大多数版本控制系统创建的目录,以及为许多编程语言生成的文件。您可以创建一个调用此命令的别名,并为您的特定问题替换
GNU查找
1 | find . ! -regex".*[/]\.svn[/]?.*" |
为此,我使用grep。把这个放进你的~/.bashrc
1 | export GREP_OPTIONS="--binary-files=without-match --color=auto --devices=skip --exclude-dir=CVS --exclude-dir=.libs --exclude-dir=.deps --exclude-dir=.svn" |
grep在调用时自动使用这些选项
创建名为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #!/bin/bash # # Attempts to behave identically to a plain `find' command while ignoring .svn/ # directories. OPTIONS=() PATHS=() EXPR=() while [[ $1 =~ ^-[HLP]+ ]]; do OPTIONS+=("$1") shift done while [[ $# -gt 0 ]] && ! [[ $1 =~ '^[-(),!]' ]]; do PATHS+=("$1") shift done # If user's expression contains no action then we'll add the normally-implied # `-print'. ACTION=-print while [[ $# -gt 0 ]]; do case"$1" in -delete|-exec|-execdir|-fls|-fprint|-fprint0|-fprintf|-ok|-print|-okdir|-print0|-printf|-prune|-quit|-ls) ACTION=;; esac EXPR+=("$1") shift done if [[ ${#EXPR} -eq 0 ]]; then EXPR=(-true) fi exec -a"$(basename"$0")" find"${OPTIONS[@]}""${PATHS[@]}" -name .svn -type d -prune -o '('"${EXPR[@]}" ')' $ACTION |
这个脚本的行为与普通的
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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; |
为什么不用grep来表达你的命令,这很容易理解:
1 | your find command| grep -v '\.svn' |
我只是想在Kaleb和其他人的帖子(详细介绍了
为了提高性能,您应该始终尝试使用
当使用
在源代码存储库中,我通常只想对文本文件执行操作。
第一行是所有文件,不包括cvs、svn和git存储库文件。
第二行排除所有二进制文件。
1 2 | 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 |
我使用find和-not-path选项。我对李子没有好运气。
1 | find . -name"*.groovy" -not -path"./target/*" -print |
将发现groovy文件不在目标目录路径中。
注意如果你这样做了
当整个表达式(
但是,要停止下降到某些目录中,您应该使用与这些目录匹配的任何内容,然后使用
对于.svn目录,此值为true,我们可以使用布尔短路,方法是:使用
只评估不在.svn目录中的文件的
请注意,由于
最后,请注意,如果省略了任何操作(
然后,
试试findrepo,它是一个简单的find/grep包装,比ack快得多。在这种情况下,您可以使用它,例如:
1 | findrepo uint 'messages.*' |
要解决此问题,只需使用以下查找条件:
1 | find \( -name 'messages.*' ! -path"*/.svn/*" \) -exec grep -Iw uint {} + |
您可以像这样添加更多限制:
1 | find \( -name 'messages.*' ! -path"*/.svn/*" ! -path"*/CVS/*" \) -exec grep -Iw uint {} + |
您可以在"Operators"的手册页部分中找到有关此的更多信息:http://unixhelp.ed.ac.uk/cgi/man-cgi?找到
这在Unix提示下对我有效
gfind . \( -not -wholename '*\.svn*' \) -type f -name 'messages.*'
-exec grep -Iw uint {} +
上面的命令将列出不带.svn的文件,并执行您提到的grep。
我通常会再次通过grep输入输出,删除.svn,在我的使用中不会慢很多。典型示例:
1 | find -name 'messages.*' -exec grep -Iw uint {} + | grep -Ev '.svn|.git|.anythingElseIwannaIgnore' |
或
1 | find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore' |