Более быстрые альтернативы «найти» и «найти»?

22

Я хотел бы использовать «поиск» и «найти» для поиска исходных файлов в моем проекте, но они требуют много времени для запуска. Существуют ли более быстрые альтернативы этим программам, о которых я не знаю, или способы повышения производительности из этих программ?

benhsu
источник
2
locateдолжно быть уже достаточно быстрым, учитывая, что он использует предварительно созданный индекс (основной оговоркой является то, что он должен быть в курсе), в то время как findдолжен читать списки каталогов.
afrazier
2
Какой локацией вы пользуетесь? mlocate намного быстрее, чем slocate (обратите внимание, что, какой бы пакет вы ни установили, команда все еще находится, так что проверьте ваш менеджер пакетов)
Paul
@benhsu, когда я запускаю find /usr/src -name fprintf.cна своем настольном компьютере OpenBSD, он возвращает расположение этих исходных файлов менее чем за 10 секунд. locate fprintf.c | grep '^/usr/src.*/fprintf.c$'возвращается через секунду. Каково ваше определение «долго бежать» и как вы используете findи locate?
Кусалананда
@Paul, я использую mlocate.
Benhsu
@ KAK, я хотел бы использовать вывод find / locate, чтобы открыть файл в emacs. Я имею в виду сценарий использования: я хочу отредактировать файл, я ввожу имя файла (или некоторое регулярное выражение, соответствующее имени файла) в emacs, и emacs будет использовать find / locate для вызова списка файлов, соответствующих ему, поэтому мне понравится время отклика, достаточно быстрое, чтобы быть интерактивным (до 1 секунды). У меня есть около 3 миллионов файлов в $ HOME, и я могу сделать так, чтобы моя команда find удалила некоторые файлы.
Benhsu

Ответы:

16

Поиск исходных файлов в проекте

Используйте более простую команду

Как правило, исходный код проекта, вероятно, находится в одном месте, возможно, в нескольких подкаталогах, вложенных не более чем в две или три глубины, поэтому вы можете использовать (возможно) более быструю команду, такую ​​как

(cd /path/to/project; ls *.c */*.c */*/*.c)

Используйте метаданные проекта

В C-проекте у вас обычно есть Makefile. В других проектах у вас может быть что-то подобное. Это может быть быстрым способом извлечения списка файлов (и их местоположения), написания скрипта, который использует эту информацию для поиска файлов. У меня есть «исходный» скрипт, чтобы я мог писать такие команды, как grep variable $(sources programname).

Ускорение найти

Ищите меньше мест, а не find / …используйте find /path/to/project …там, где это возможно. Упростите критерии выбора, насколько это возможно. Используйте конвейеры, чтобы отложить некоторые критерии выбора, если это более эффективно.

Также вы можете ограничить глубину поиска. Для меня это значительно повышает скорость поиска. Вы можете использовать ключ -maxdepth. Например, '-maxdepth 5'

Ускорение найти

Убедитесь, что он индексирует интересующие вас местоположения. Прочтите справочную страницу и используйте любые параметры, подходящие для вашей задачи.

   -U <dir>
          Create slocate database starting at path <dir>.

   -d <path>
          --database=<path> Specifies the path of databases to search  in.


   -l <level>
          Security  level.   0  turns  security checks off. This will make
          searchs faster.   1  turns  security  checks  on.  This  is  the
          default.

Убрать необходимость поиска

Может быть, вы ищете, потому что вы забыли, где что-то или не было сказано. В первом случае пишите заметки (документацию), во втором спрашивайте? Соглашения, стандарты и последовательность могут очень помочь.

RedGrittyBrick
источник
10

Я использовал «ускорение поиска» части ответа RedGrittyBrick. Я создал меньшую БД:

updatedb -o /home/benhsu/ben.db -U /home/benhsu/ -e "uninteresting/directory1 uninteresting/directory2"

затем указал locateна это:locate -d /home/benhsu/ben.db

benhsu
источник
6

Тактика, которую я использую, заключается в применении -maxdepthопции с find:

find -maxdepth 1 -iname "*target*"

Повторяйте с увеличением глубины, пока не найдете то, что ищете, или устали смотреть. Первые несколько итераций, вероятно, вернутся мгновенно.

Это гарантирует, что вы не тратите время впустую, просматривая глубины массивных поддеревьев, когда то, что вы ищете, с большей вероятностью будет находиться у основания иерархии.


Вот пример сценария для автоматизации этого процесса (Ctrl-C, когда вы видите, что вы хотите):

(
TARGET="*target*"
for i in $(seq 1 9) ; do
   echo "=== search depth: $i"
   find -mindepth $i -maxdepth $i -iname "$TARGET"
done
echo "=== search depth: 10+"
find -mindepth 10 -iname $TARGET
)

Обратите внимание, что связанная с этим избыточность (каждый проход должен проходить через папки, обработанные в предыдущих проходах) будет в значительной степени оптимизирована за счет кэширования диска.

Почему findэтот порядок поиска не встроен? Возможно, потому что это было бы сложно / невозможно реализовать, если вы предполагали, что избыточный обход недопустим. Наличие -depthопции намекает на возможность, но увы ...

nobar
источник
1
... таким образом, выполняя поиск в ширину.
Нобар
3

Другое простое решение - использовать более новую расширенную оболочку. Включить:

  • bash: shopt -s globstar
  • ksh: set -o globstar
  • zsh: уже включен

Затем вы можете запускать такие команды в исходном каталоге верхнего уровня:

# grep through all c files
grep printf **/*.c

# grep through all files
grep printf ** 2>/dev/null

Это имеет то преимущество, что он рекурсивно просматривает все подкаталоги и работает очень быстро.

dannyw
источник
3

Серебряный Искатель

Вы можете найти его полезным для очень быстрого поиска содержимого огромного количества файлов исходного кода. Просто введите ag <keyword>. Вот некоторые из моих выводов apt show silversearcher-ag:

Я обычно использую это с:

-G --file-search-regex PATTERN Искать только те файлы, имена которых соответствуют PATTERN.

ag -G "css$" important

Скриншот

Пабло А
источник
1
в ripgrep в алгоритм якобы быстрее , чем silversearch, а также чтит .gitignoreфайлы и пропуски .git, .svn, .hg.. папки.
ccpizza
@ccpizza Так? Silver Searcher также чтит .gitignoreи игнорирует скрытые и бинарные файлы по умолчанию. Также есть больше участников, больше звезд на Github (14700 против 8300) и уже на репо мэров дистрибутивов. Пожалуйста, предоставьте обновленное сравнение достоверных сторонних источников. Тем не менее, ripgrepвыглядит отличный кусок программного обеспечения.
Пабло А
хорошо знать! Я ripgrepникоим образом не связан с автором (ами) , это просто соответствует моим требованиям, поэтому я перестал искать другие варианты.
ccpizza
Серебряный искатель .gitignoreтоже уважает . Тем не менее, rgэто совершенно потрясающе. Во-первых, он поддерживает Unicode. По моему опыту, rgпо крайней мере, вдвое быстрее, чем ag(YMMV), я предполагаю, что это из-за синтаксического анализатора регулярных выражений Rust, который, очевидно, еще не был готов, еще в те годы он agбыл новым. rgможет выдавать детерминированный вывод (но не по умолчанию), он может заносить в черный список типы файлов, где agможет быть только белый список, он может игнорировать файлы в зависимости от размера (до свидания, журналы). Я все еще использую agв случае, если мне нужно многострочное сопоставление, что rgне может сделать.
Pellmeister
2

Для замены найти, проверьте FD . Он имеет более простой / более интуитивно понятный интерфейс, чем оригинальная команда поиска, и немного быстрее.

Кит Хьюджитт
источник