I often use the find
command 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 uint
in multiple messages.h
and messages.cpp
files:
# 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 find
to ignore the .svn
directories?
Update: If you upgrade your SVN client to version 1.7 this is no longer an issue.
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.
find ... -print0 | xargs -0 egrep ...
instead offind ... -exec grep ...
(does not forkgrep
for each file, but for a bunch of files at a time). Using this form you can also prune.svn
directories without using the-prune
option of find, i.e.find ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...
– Starknaked-exec
with+
doesn't forkgrep
for each file, while using it with;
does. Using-exec
is actually more correct than usingxargs
. Please notice that commands likels
do something even if the argument list is empty, while commands likechmod
give an error if there is insufficient arguments. To see what I mean, just try the following command in a directory that does not have any shell script:find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755
. Compare with this one:find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'
. – Icterusgrep
-ing out.svn
is not a good idea too. Whilefind
is specialized for handling file properties,grep
does not. In your example, a file named '.svn.txt' will also be filtered by youregrep
command. Although you can modify your regex to '^/\.svn$', it is still not a good practice to do so. The-prune
predicate offind
works perfectly for filtering a file (by filename, or creation timestamp, or whatever condition you supplied). It is just like even if you can kill a cockroach using a big sword doesn't mean it is the suggested way to do so :-). – Icterus