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

670

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

TIMEX
источник
3
Смотрите superuser.com/q/66715/59933
ужасный
14
Просто введите "man grep", и вы увидите --exclude и опции --exclude-dir, перечисленные прямо здесь - из заголовка этого вопроса, я предполагаю, что вы уже знали о grep ...
arcseldon
35
Если вы ищите код в git-репозитории и node_modulesиспользуете свой .gitignore, git grep "STUFF"это самый простой способ. git grepищет отслеживаемые файлы в рабочем дереве, игнорируя все из.gitignore
0xcaff
2
Пример для узла: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- кроме того, вы всегда можете присвоить псевдониму в оболочке значение 'nodegrep' или что-либо еще и использовать аргумент команды в качестве строкового ввода ..
bshea

Ответы:

395

РЕШЕНИЕ 1 (объединить findи grep)

Цель этого решения не в том, чтобы иметь дело с grepпроизводительностью, а в том, чтобы продемонстрировать переносимое решение: оно также должно работать с занятой версией или 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

Чтобы исключить несколько каталогов, используйте --exclude-dirкак:

--exclude-dir={node_modules,dir1,dir2,dir3}

РЕШЕНИЕ 3 (Ag)

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

hornetbzz
источник
2
эта комбинация ищет быстрее, чем --exclude-dir=dirи показывает результаты с цветами - легко читаемо
Максим Ефремов
27
«эта комбинация» find ... -execне быстрее чем grep --exclude-dirдля меня. Огромное преимущество в Grep (примерно в пять раз быстрее 26K + файлы, отфильтрованных 38K + на HDD), если не заменить \;с +для поиска / ехес комбо. Тогда grep «только» примерно на 30% быстрее. Синтаксис grep также удобен для чтения :).
Кьелл Андреассен
Договорились, так как это очевидно. У некоторых busyboxes нет команды GREP.
hornetbzz
10
Также отметим, что вы можете исключить множественное число с--exclude-dir={dir1,dir2}
Suh
4
Я нисколько не удивлен, что node_modulesэто канонический пример.
pdoherty926
984

Последние версии 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( Edit : или The Silver Searcher ) и покончите с этим!

Johnsyweb
источник
4
@Manocho: Если вы думаете, что ackэто здорово, попробуйте Серебряный Искатель и увидите увеличение скорости!
Johnsyweb
30
Синтаксис для нетерпеливых: --exclude-dir=dirиспользует grepшаблоны регулярных выражений, а не глобализацию файлов оболочки. Шаблоны работают на пути относительно вашего текущего каталога. Так что используйте шаблон --exclude-dir=dir, а не --exclude-dir="/root/dir/*".
Tanius
15
Если вы хотите исключить несколько директорий из поиска, есть лучший вариант , чем использование: $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir?
Даршан Чаудхари
4
Вероятно, я потратил на это слишком много времени, чем любой здравомыслящий человек, но я не могу понять, как исключить подкаталог из поиска - grep -r --exclude-dir=public keyword .работает, но grep -r --exclude-dir='public/dist' keyword .не работает. Я пытался добавить подстановочные знаки регулярных выражений, экранировать символы и т. Д., Но ничего не помогло.
Дкобозев
73
Исключить несколько каталогов, например, так:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97
78

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

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

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

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

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

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

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

Azodium
источник
5
ПРИМЕЧАНИЕ: не добавляйте пробелы после запятых в{dir1,dir2,dir3}
skplunkerin
Спасибо, удобно, когда grep'ing через рабочее пространство SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237
1
Вы можете просто предоставить --exclude-dirопцию несколько раз.
Уолф
45

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

--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.

Дерек Вейт
источник
14

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

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

Собрав все вместе, вы получите что-то вроде:

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

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

Пример:

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

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

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

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

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

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
arcseldon
источник
Я считаю, что параметр «r» должен быть напечатан заглавными буквами «-R».
hornetbzz
1
Интересно. «r» всегда работал для меня на nix и mac.
arcseldon
Когда я писал свой ответ , я использовал -R(я не помню, почему сейчас). Я обычно использую -r. Оказывается, что заглавная версия следует за символическими ссылками . TIL.
Johnsyweb
@Johnsyweb - спасибо. проголосовал за ваш ответ - не помню, когда, вероятно, в 2016 году, когда я добавил этот :)
arcseldon
10

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

DIP-переключатель
источник
34
Не очень хорошее решение в некоторых случаях. Например: если каталог 'node_modules' является огромным с большим количеством ложноположительных совпадений (отсюда и необходимость отфильтровывать каталог), то первый grep тратит много времени на поиск в подкаталоге, а затем - на второй grep-фильтрацию. вне матчей. Быстрее исключить node_modules в самом первом grep.
ГуруМ 13.12.12
2
меня не волнует медлительность, я могу посмотреть на команду и узнать, что она делает
Funkodebat
1
То же самое для комментария Гуру. Грех /varзависает, когда он попадает /var/runв моем случае. Отсюда и причина, по которой я хочу избежать каталога.
jww
3
--exclude-dirлучшее решение с 2016 года.
Омар Тарик
10

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

git grep "STUFF"
0xcaff
источник
Это очень полезный совет. Спасибо.
NKM
4

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

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
Нестор Уркиса
источник
2

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

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

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

Выполнено.

помет
источник
Аккуратный, в том числе несколько каталогов в скобках
Mijo
2

Здесь было дано много правильных ответов, но я добавляю этот, чтобы подчеркнуть один момент, который вызвал некоторые спешные попытки потерпеть неудачу раньше: exclude-dirберет образец , а не путь к каталогу.

Скажите, что ваш поиск:

grep -r myobject

И вы заметили, что ваши результаты загромождены результатами из src/other/objects-folder. Эта команда не даст вам ожидаемого результата:

grep -r myobject --exclude-dir=src/other/objects-folder

И вы можете удивиться, почему exclude-dirне работает! Чтобы фактически исключить результаты из objects-folder, просто сделайте это:

grep -r myobject --exclude-dir=objects-folder

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

Со страницы руководства:

--exclude-dir = GLOB
Пропустить любой каталог командной строки с суффиксом имени, соответствующим шаблону GLOB. При поиске рекурсивно пропустите любой подкаталог, базовое имя которого соответствует GLOB. Игнорируйте любые лишние конечные косые черты в GLOB.

Nagev
источник
2

Этот работает для меня:

grep <stuff> -R --exclude-dir=<your_dir>
angelo.mastro
источник
5
Чем этот ответ отличается от того, что уже было опубликовано?
17
-1

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

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

Моррис
источник
12
Это фактически тот же ответ, который DipSwitch дал 3 года назад. У него тоже такие же проблемы.
jww