Используйте синтаксис grep --exclude / - include, чтобы не просматривать определенные файлы - PullRequest
720 голосов
/ 21 октября 2008

Я ищу строку foo= в текстовых файлах в дереве каталогов. Это на обычной машине Linux, у меня есть оболочка bash:

grep -ircl "foo=" *

В каталогах также много бинарных файлов, которые соответствуют "foo =". Поскольку эти результаты не релевантны и замедляют поиск, я хочу, чтобы grep пропустил поиск этих файлов (в основном изображений JPEG и PNG). Как бы я это сделал?

Я знаю, что есть опции --exclude=PATTERN и --include=PATTERN, но каков формат шаблона? На странице руководства grep написано:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

Поиск по grep include , grep include exclude , grep exclude и варианты не нашли ничего релевантного

Если есть лучший способ поиска только в определенных файлах, я все для этого; перемещение оскорбительных файлов не вариант. Я не могу искать только определенные каталоги (структура каталогов - большой беспорядок, со всем везде). Кроме того, я ничего не могу установить, поэтому мне приходится иметь дело с обычными инструментами (такими как grep или с предложением find ).

Ответы [ 22 ]

693 голосов
/ 21 октября 2008

Использовать синтаксис глобализации оболочки:

grep pattern -r --include=\*.{cpp,h} rootdir

Синтаксис для --exclude идентичен.

Обратите внимание, что звезду экранируют обратной косой чертой, чтобы не допустить ее расширения оболочкой (цитирование, например --include="*.{cpp,h}", также будет работать). В противном случае, если у вас есть какие-либо файлы в текущем рабочем каталоге, которые соответствуют шаблону, командная строка будет расширена до чего-то вроде grep pattern -r --include=foo.cpp --include=bar.h rootdir, что будет искать только файлы с именами foo.cpp и bar.h, что, скорее всего, не то, что вы хотел.

211 голосов
/ 21 октября 2008

Если вы просто хотите пропустить двоичные файлы, я предлагаю вам взглянуть на параметр -I (верхний регистр i). Он игнорирует двоичные файлы. Я регулярно использую следующую команду:

grep -rI --exclude-dir="\.svn" "pattern" *

Он выполняет рекурсивный поиск, игнорирует двоичные файлы и не ищет в скрытых папках Subversion какой-либо шаблон, который мне нужен. Я имею псевдоним "grepsvn" на моей коробке на работе.

62 голосов
/ 21 октября 2008

Пожалуйста, посмотрите на ack , который предназначен именно для этих ситуаций. Ваш пример

grep -ircl --exclude=*.{png,jpg} "foo=" *

делается с ack как

ack -icl "foo="

потому что ack никогда не просматривает двоичные файлы по умолчанию, а -r включен по умолчанию. А если вам нужны только файлы CPP и H, просто сделайте

ack -icl --cpp "foo="
34 голосов
/ 04 февраля 2009

grep 2.5.3 ввел параметр --exclude-dir, который будет работать так, как вы хотите.

grep -rI --exclude-dir=\.svn PATTERN .

Вы также можете установить переменную окружения: GREP_OPTIONS = "- exclude-dir = .svn"

Я буду вторым Энди проголосует за ack хотя, это лучшее.

24 голосов
/ 20 декабря 2012

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

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js
12 голосов
/ 17 декабря 2008

Предлагаемая команда:

grep -Ir --exclude="*\.svn*" "pattern" *

концептуально неверно, потому что --exclude работает с базовым именем. Другими словами, он пропустит только .svn в текущем каталоге.

11 голосов
/ 01 апреля 2010

В grep 2.5.1 вы должны добавить эту строку в профиль ~ / .bashrc или ~ / .bash

export GREP_OPTIONS="--exclude=\*.svn\*"
9 голосов
/ 21 октября 2008

Иногда вывод grep очень полезен:

grep -rn "foo=" . | grep -v "Binary file"

Хотя это не мешает искать двоичные файлы.

7 голосов
/ 07 ноября 2014

В CentOS 6.6 / Grep 2.6.3 я должен использовать его так:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

Обратите внимание на отсутствие знаков равенства "=" (в противном случае --include, --exclude, include-dir и --exclude-dir игнорируются)

6 голосов
/ 15 ноября 2011

Если вы не против использования find, мне нравится его -prune функция: find [directory] \ -name "pattern_to_exclude" -prune \ -o -name "another_pattern_to_exclude" -prune \ -o -name "pattern_to_INCLUDE" -print0 \ | xargs -0 -I FILENAME grep -IR "pattern" FILENAME

В первой строке вы указываете каталог, который хотите найти. . (текущий каталог) является допустимым путем, например.

Во 2-й и 3-й строках используйте "*.png", "*.gif", "*.jpg" и т. Д. Используйте столько конструкций -o -name "..." -prune, сколько у вас есть шаблонов.

В 4-й строке вам нужен еще один -o (он указывает "или" на find), паттерны, которые вам НУЖНЫ, и вам нужно либо -print, либо -print0 в конце. Если вы просто хотите, чтобы «все остальное» оставалось после удаления изображений *.gif, *.png и т. Д., Используйте -o -print0 и вы закончили с 4-й строкой.

Наконец, на 5-й строке находится канал к xargs, который берет каждый из этих полученных файлов и сохраняет их в переменной FILENAME. Затем он передает grep флаги -IR, "pattern", а затем FILENAME расширяется на xargs, чтобы стать тем списком имен файлов, найденных find.

По вашему конкретному вопросу утверждение может выглядеть примерно так: find . \ -name "*.png" -prune \ -o -name "*.gif" -prune \ -o -name "*.svn" -prune \ -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...