Я часто использую find
команда для поиска исходного кода удалите файлы, безотносительно. Раздражающе, потому что Подверсия хранит дубликаты каждого файла в .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, это больше не проблема.
Основной характеристикой изменений, представленных в Подверсии 1.7, является централизация рабочего устройства хранения данных метаданных копии в единственное местоположение. Вместо a
.svn
каталог в каждом каталоге в рабочей копии, Подверсия 1,7 рабочих копии имеют всего один.svn
каталог — в корне рабочей копии. Этот каталог включает (среди прочего) SQLite-поддержанную базу данных, которая содержит все потребности Подверсии метаданных в той рабочей копии.
Могу я предложить вам для поиска посмотреть ack ? Это find
, поддерживающий исходный код, и поэтому он автоматически игнорирует многие типы файлов, включая информацию о репозитории исходного кода, такую как указанная выше.
Попробуйте findrepo , который представляет собой простую оболочку для find / grep и намного быстрее, чем ack {{1} } Вы могли бы использовать его в этом случае, например:
findrepo uint 'messages.*'
Как указано ниже:
find . -path '*/.svn*' -prune -o -print
Или, альтернативно, на основе каталога, а не префикса пути:
find . -name .svn -a -type d -prune -o -print
Почему бы вам не передать команду с помощью grep, который легко понять:
your find command| grep -v '\.svn'
Создайте сценарий под названием ~ / bin / svnfind
:
#!/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
Этот сценарий ведет себя идентично обычному find
, но она удаляет каталоги .svn
. В остальном поведение идентично.
Пример:
# 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;
wcfind
- это сценарий-оболочка поиска, который я использую для автоматического удаления каталогов .svn.
Я использую для этой цели grep. Поместите это в свой ~ / .bashrc
export GREP_OPTIONS="--binary-files=without-match --color=auto --devices=skip --exclude-dir=CVS --exclude-dir=.libs --exclude-dir=.deps --exclude-dir=.svn"
grep автоматически использует эти параметры при вызове
Просто подумал, что добавлю простую альтернативу к сообщениям Калеба и других (в которых подробно описано использование опции find -prune
, ack
, repofind
команд и т. Д.), Что особенно применимо к использованию, которое вы описали в вопросе (и любых других подобных использованиях):
Для повышения производительности вы всегда должны пытаться использовать find ... -exec grep ... +
(спасибо Kenji за указание на это) или find ... | xargs egrep ...
(переносимый) или find ... -print0 | xargs -0 egrep ...
(GNU; работает с именами файлов, содержащими пробелы) вместо из find ... -exec grep ... \;
.
find ... -exec ... +
и find | Форма xargs
не разветвляет egrep
для каждого файла, а скорее для группы файлов за раз, что приводит к гораздо более быстрому выполнению .
При использовании найти | xargs
, вы также можете использовать grep
, чтобы легко и быстро удалить .svn
(или любые каталоги или регулярное выражение), то есть find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...
(полезно, когда вам нужно что-то быстрое и вы не беспокоитесь о том, как настроить логику find
-prune
.)
Находка | grep | xargs
подход похож на GNU find
параметр -regex
(см. сообщение ghostdog74
), но более переносимый (также будет работать на платформы, на которых GNU find
недоступен.)
почему бы не просто
find . -not -iwholename '*.svn*'
Предикат -not отменяет все, что имеет .svn где-либо на пути.
Итак, в вашем случае это будет
find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;