Как я могу исключить каталоги из grep -R?

441

Я хочу пройти все подкаталоги, за исключением каталога node_modules.

  • 3
    См. Superuser.com/q/66715/59933
  • 9
    Просто введите "man grep", и вы увидите --exclude и --exclude-dir, перечисленные здесь, прямо из заголовка этого вопроса. Я предполагаю, что вы уже знали о grep ...
Показать ещё 3 комментария
Теги:
grep

12 ответов

154
Лучший ответ

РЕШЕНИЕ 1 (комбинировать find и grep)

Цель этого решения заключается не в том, чтобы иметь дело с эффективностью grep а в том, чтобы показать портативное решение: также следует работать с версией busybox или GNU старше 2.5.

Используйте find, для исключения каталогов foo и bar:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Затем комбинируйте find и нерекурсивное использование grep в качестве переносного решения:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

РЕШЕНИЕ 2 (рекурсивное использование grep):

Вы уже знаете это решение, но я добавляю его с самого последнего и эффективного решения. Обратите внимание, что это менее портативное решение, но более понятное для человека.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

РЕШЕНИЕ 3 (Ag)

Если вы часто просматриваете код, Ag (The Silver Searcher) является гораздо более быстрой альтернативой grep, настроенной для поиска кода. Например, он автоматически игнорирует файлы и каталоги, перечисленные в .gitignore, поэтому вам не нужно передавать те же громоздкие опции исключения в grep или find.

  • 2
    эта комбинация ищет быстрее, чем --exclude-dir=dir и показывает результаты с цветами - легко читается
  • 21
    "эта комбинация" find ... -exec не быстрее, чем grep --exclude-dir для меня. Огромное преимущество grep (примерно в пять раз быстрее с 26k + файлами, отфильтрованными из 38k + на жестком диске), если вы не замените \; с + для комбинации поиска / исполнения. Тогда grep «только» примерно на 30% быстрее. Синтаксис grep также удобен для чтения :).
Показать ещё 6 комментариев
892

Последние версии GNU Grep ( >= 2.5.2):

--exclude-dir=dir

который исключает каталоги, соответствующие шаблону dir из поиска в рекурсивном каталоге.

Итак, вы можете сделать:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Для получения дополнительной информации о синтаксисе и использовании см.

Для более старых GNU Greps и POSIX Grep используйте find, как предложено в других ответах.

Или просто используйте ack (Изменить: или Серебряный Searcher) и сделайте это!

  • 0
    Я только что попробовал. работает отлично.
  • 4
    @Manocho: Если вы думаете, что ack - это здорово, попробуйте The Silver Searcher и увидите увеличение скорости!
Показать ещё 14 комментариев
58

Если вы хотите исключить несколько каталогов:

"r" для рекурсивного "l" для печати только имен файлов, содержащих совпадения, и "i" для игнорирования различий в случае:


grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Пример: Я хочу найти файлы, содержащие слово "привет". Я хочу выполнить поиск во всех каталогах Linux , кроме proc, загрузочной директории, sys и root:


grep -rli --exclude-dir={proc,boot,root,sys} hello /

Примечание. Пример выше должен быть root

Примечание 2 (согласно @skplunkerin): не добавляйте пробелы после запятых в {dir1,dir2,dir3}

  • 4
    ПРИМЕЧАНИЕ: не добавляйте пробелы после запятых в {dir1,dir2,dir3}
  • 0
    Спасибо, удобно, когда grep'ing в рабочей области SVN: grep -Irsn --exclude-dir=.svn 'foo' .
Показать ещё 1 комментарий
18

Этот синтаксис

--exclude-dir={dir1,dir2}

расширяется оболочкой (например, Bash), а не grep, в это:

--exclude-dir=dir1 --exclude-dir=dir2

Цитирование будет препятствовать расширению оболочки, поэтому это не сработает:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Шаблоны, используемые с --exclude-dir - это те же шаблоны, которые описаны на странице руководства для опции --exclude:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

Обычно оболочка пытается расширить такой шаблон, поэтому, чтобы этого избежать, вы должны процитировать его:

--exclude-dir='dir?'

Вы можете использовать фигурные скобки и процитировать шаблоны исключения следующим образом:

--exclude-dir={'dir?','dir??'}

Шаблон может охватывать несколько сегментов пути:

--exclude-dir='some*/?lse'

Это исключало бы каталог, например topdir/something/else.

13

Часто используйте это:

grep может использоваться в сочетании с -r (рекурсивный), i (игнорировать регистр) и -o (печатает только соответствующую часть строк). Чтобы исключить files, используйте --exclude и для исключения каталогов используйте --exclude-dir.

Объединяя это, вы получите что-то вроде:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

Описывая это, он звучит намного сложнее, чем есть на самом деле. Легче проиллюстрировать простым примером.

Пример:

Предположим, что я ищу текущий проект для всех мест, где я явно задал строковое значение debugger во время сеанса отладки и теперь хочу просмотреть/удалить.

Я пишу script под названием findDebugger.sh и использую grep, чтобы найти все вхождения. Однако:

Для исключений файлов - я хочу убедиться, что .eslintrc игнорируется (на самом деле это правило linting о debugger, поэтому его следует исключить). Аналогичным образом, я не хочу, чтобы мои собственные script указывались в любых результатах.

Для исключений каталогов - я хочу исключить node_modules, поскольку он содержит множество библиотек, которые ссылаются на debugger, и мне не интересны эти результаты. Также я просто хочу опустить скрытые каталоги .idea и .git, потому что я не забочусь об этих местах поиска, и хочу сохранить результаты поиска.

Итак, вот результат - я создаю script, называемый findDebugger.sh, с помощью:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
  • 0
    Я считаю, что параметр «r» должен быть напечатан заглавными буквами «-R».
  • 1
    Интересно. «r» всегда работал для меня на nix и mac.
8

Вы можете попробовать что-то вроде grep -R search . | grep -v '^node_modules/.*'

  • 32
    Не очень хорошее решение в некоторых случаях. Например: если каталог 'node_modules' является огромным с большим количеством ложноположительных совпадений (отсюда и необходимость отфильтровывать каталог), то первый grep тратит много времени на поиск в подкаталоге, а затем - на второй grep-фильтрацию. вне матчей. Быстрее исключить node_modules в самом первом grep.
  • 2
    меня не волнует медлительность, я могу посмотреть на команду и узнать, что она делает
Показать ещё 2 комментария
4

Очень полезно, особенно для тех, кто имеет дело с Node.js, где мы хотим избежать поиска внутри "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
2

этот работает для меня

grep <stuff> -R --exclude-dir=<your_dir>

  • 4
    Чем этот ответ отличается от того, что уже было опубликовано?
2

Простая рабочая команда:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Выше я grep для текста "creativecommons.org" в текущем каталоге "dspace" и исключить dirs {log, assetstore}.

Готово.

  • 0
    Аккуратный, в том числе несколько каталогов в скобках
1

Если вы используете grepping для кода в git-репозитории, а node_modules находится в вашем .gitignore, вы можете использовать git grep. git grep ищет отслеживаемые файлы в рабочем дереве, игнорируя все из .gitignore

git grep "STUFF"
1
find . ! -name "node_modules" -type d 
  • 1
    Вы можете передать вышеупомянутое coomand в "grep -R" по трубе и xargs ...
0

Более простой способ - отфильтровать результаты с помощью grep -v.

grep -i needle -R * | grep -v node_modules

  • 9
    По сути, это тот же ответ, который DipSwitch дал 3 года назад. У него тоже такие же проблемы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню