Я часто використовую 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;
Як я можу сказати find
ігнорувати .svn
каталоги?
Оновлення : Якщо ви оновите клієнт SVN до версії 1.7, це більше не є проблемою.
Ключовою особливістю змін, внесених у Subversion 1.7, є централізація зберігання метаданих робочої копії в одне місце. Замість
.svn
каталогу в кожному каталозі робочої копії Subversion 1.7 робочі копії мають лише один.svn
каталог - у корені робочої копії. Цей каталог включає (серед іншого) базується на SQLite базі даних, яка містить усі необхідні метадані Subversion для цієї робочої копії.
-exec
з +
не fork grep
для кожного файлу, тоді як використовуючи його з ;
do. Використання -exec
насправді правильніше, ніж використання xargs
. Зауважте, що команди, як-от, ls
роблять щось, навіть якщо список аргументів порожній, тоді як команди на зразок chmod
дають помилку, якщо аргументів недостатньо. Для того, щоб побачити , що я маю в виду, просто спробуйте наступну команду в каталозі , який не має будь - яких скрипт: find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755
. Порівняйте з цим: find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'
.
grep
-ing out теж .svn
не є хорошою ідеєю. Хоча find
спеціалізується на обробці властивостей файлів, grep
це не так. У вашому прикладі файл з назвою ".svn.txt" також буде відфільтрований вашою egrep
командою. Хоча ви можете змінити свій регулярний вираз на "^ / \. Svn $" , це все ще не є хорошою практикою. -prune
Предикат find
відмінно працює для фільтрації файлів (по імені файлу, або створення тимчасової мітки, або незалежно від стану ви додається). Це так само, як навіть якщо ви можете вбити таргана великим мечем, не означає, що це запропонований спосіб зробити це :-).
find ... -print0 | xargs -0 egrep ...
замістьfind ... -exec grep ...
(не вилкаgrep
для кожного файлу, а для групи файлів одночасно). За допомогою цієї форми ви також можете обрізати.svn
каталоги, не використовуючи-prune
опцію пошуку, тобтоfind ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...