Я часто використовую 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 ...