рекурсивный 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

0

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

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

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

grep -R "myfunc" . | grep -v log/
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.