Często używam find
polecenia do przeszukiwania kodu źródłowego, usuwania plików, cokolwiek. Irytujące, ponieważ Subversion przechowuje duplikaty każdego pliku w swoich .svn/text-base/
katalogach, moje proste wyszukiwania kończą się uzyskaniem wielu duplikatów wyników. Na przykład, chcę rekursywnie szukać uint
w wielokrotności messages.h
i messages.cpp
plików:
# 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;
Jak mogę find
zignorować .svn
katalogi?
Aktualizacja : jeśli uaktualnisz swojego klienta SVN do wersji 1.7, nie będzie to już problemem.
Kluczową cechą zmian wprowadzonych w Subversion 1.7 jest centralizacja przechowywania metadanych kopii roboczej w jednym miejscu. Zamiast
.svn
katalogu w każdym katalogu w kopii roboczej, kopie robocze Subversion 1.7 mają tylko jeden.svn
katalog - w katalogu głównym kopii roboczej. Ten katalog zawiera (między innymi) bazę danych opartą na SQLite, która zawiera wszystkie potrzebne metadane Subversion dla tej kopii roboczej.
-exec
z +
nie rozwidla grep
dla każdego pliku, podczas gdy używanie z ;
robi. Używanie -exec
jest właściwie bardziej poprawne niż używanie xargs
. Zauważ, że polecenia takie jak ls
coś robią, nawet jeśli lista argumentów jest pusta, podczas gdy polecenia takie chmod
dają błąd, jeśli nie ma wystarczających argumentów. Aby zobaczyć, co mam na myśli, po prostu spróbuj następującą komendę w katalogu, który nie ma żadnego skrypt: find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755
. Porównaj z tego: find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'
.
grep
rezygnacja .svn
nie jest dobrym pomysłem. Chociaż find
jest wyspecjalizowany w obsłudze właściwości plików, grep
nie robi tego. W twoim przykładzie plik o nazwie „.svn.txt” również zostanie odfiltrowany przez twoje egrep
polecenie. Chociaż możesz zmodyfikować wyrażenie regularne na „^ / \. Svn $” , nadal nie jest to dobrą praktyką. -prune
Orzecznik find
działa idealnie do filtrowania plików (według nazwy pliku lub tworzenia datownik, czy cokolwiek warunek ty zestawie). To tak, jakby nawet jeśli możesz zabić karalucha za pomocą dużego miecza, nie oznacza to, że jest to sugerowany sposób :-).
find ... -print0 | xargs -0 egrep ...
zamiastfind ... -exec grep ...
(nie rozwidla sięgrep
dla każdego pliku, ale dla kilku plików jednocześnie). Za pomocą tego formularza można również przycinać.svn
katalogi bez korzystania z-prune
opcji find, tj.find ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...