рекурсивный grep: исключить определенные каталоги

49

Я часто использую рекурсивный grep для поиска исходных файлов с конкретным контентом.

grep -Rni "myfunc" .

На больших кодовых базах это может быть медленным, поэтому я использую --incldue для ограничения расширений / белых списков.

grep -Rni --include=*.java "myfunc" .

Тем не менее, было бы более эффективно исключить (удалить) целые подкаталоги, я думаю:

grep -Rni --exclude=/.svn/ "myfunc" .

Но --exclude поддерживает только шаблоны файлов, такие как * .java выше. Как я могу исключить каталоги?

Габор
источник

Ответы:

10

Вы можете посмотреть в АСК .

Я только начал использовать это, но это кажется подходящим для этого.

Алекс Фейнман
источник
Ack выглядит довольно хорошо. Приятно, что он интуитивно исключает ненужные файлы. опция --nogroup дает аналогичный вывод для grep -Rni
gabor
2
Ack немного медленный. Вы можете попробовать Серебряный Искатель (Ag) или ripgrep (rg).
user31389
63
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Источник: https://stackoverflow.com/questions/2799246/grep-exclusive-a-specific-folder-using

Хенрик
источник
17
Обратите внимание, что это рекурсивно исключает. ./devбудут исключены ПОСЛЕ ./foo/bar/dev. Используйте --exclude-dir=./devтолько для первого случая.
Кори Уокер
4
Вы также можете немного сократить это, используя globbing: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data единственная проблема с globbing - это то, что я не могу заставить его работать в моем bash. В этом случае я должен держать их отдельно.
b01
3
Также отмечено, что {} работает, только если вы добавили более 1 записей, это означает, что --exclude-dir = {home, .svn} работает, но --exclude-dir = {. Svn} не будет работать. Я трачу время на то, чтобы понять, почему {} не работает, потому что сначала я тестирую с 1 записью.
皞 皞
Если вы используете {}одну запись, вам, вероятно, понадобится унарная запятая, чтобы сделать ее массивом (не уверен, как Bash справится с этим). Вместо этого я создал псевдоним в своем .bash_aliases, который зацикливает список папок, которые я обычно всегда хочу исключить, например .git, .svn, .hg, .cache, и затем я добавляю их через цикл с --exclude-dir $dirа затем разверните этот массив в псевдоним grep.
dragon788
6

вы можете использовать вместо поиска:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

Итак, это немного задом наперед, сначала вы получите результаты grep, а затем путь. Может быть, у кого-то еще есть лучший ответ?

мистифицировать
источник
3
хорошо, мне это очень нравится. конечно найти намного гибче. единственная разница между выходными данными состоит в том, что «grep -Rni» будет печатать имя файла для каждого совпадения, тогда как «find -exec grep» будет печатать имя файла в одной строке, а затем по одной строке для каждого соответствия (с номером строки и содержимым строки ). использование «grep -Hni» заставляет имя файла отображаться в каждой строке
gabor
Спасибо за предоставленный единственный ответ, который работал для систем, которые являются такими хрустящими, без grep --exclude-dir, но все еще должны работать
Дмитрий Д.Б.
2

Вот полный пример скрипта в одном из моих проектов, который может помочь, я называю этот файл «all_source» (помеченный как исполняемый файл) и помещаю его в корневой каталог моего проекта, затем называю его grep myfunc $(./all_source)сортировкой в ​​конце скрипта полностью по желанию.

#!/bin/bash

find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

Этот скрипт возвращает все имена файлов в проекте, которые совпадают *.h, *.cpp, *.c, *.lua, *.*awk, но не выполняет поиск во всех папках с именами .svn и gen, а также пропускает папки ./libи ./vc6(но только те, которые находятся прямо в корне проекта). Поэтому, когда вы делаете grep myfunc $(./all_source)это только greps в этих файлах. Вам также нужно будет вызвать это из корневого каталога проекта.

Майк Нельсон
источник
0

Существует также опция -prune, чтобы найти:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
misiu_mp
источник
0

Вы можете попробовать сделать это:

grep -R  "myfunc" . | grep -v path_to_exclude/

Например: если вы не хотите искать содержимое в файлах журналов, просто сделайте следующее:

grep -R "myfunc" . | grep -v log/
Акшатха
источник