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

564

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

grep -ircl "foo=" *

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

Я знаю, что есть опции --exclude=PATTERN и --include=PATTERN, но каков формат шаблона? На странице man 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 и варианты не нашли ничего подходящего

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

  • 12
    Просто FYI, используемые аргументы: -c подсчитывать совпадения в файле -i без учета регистра -l показывать только совпадающие файлы -r рекурсивно
  • 67
    Более быстрый способ исключить svn dirs - --exclude-dir=.svn , так что grep вообще не --exclude-dir=.svn в них
Показать ещё 2 комментария
Теги:
grep
search
command-line

20 ответов

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

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

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, что вполне вероятно не то, что вы хотел.

  • 6
    Я не знаю почему, но мне пришлось процитировать шаблон включения следующим образом: grep pattern -r --include="*.{cpp,h}" rootdir
  • 5
    @topek: Хорошая мысль - если у вас есть какие-либо файлы .cpp / .h в вашем текущем каталоге, то оболочка расширит глобус перед вызовом grep, так что вы получите командную строку, такую как grep pattern -r --include=foo.cpp --include=bar.h rootdir , который будет искать только файлы с именем foo.cpp или bar.h Если у вас нет файлов, которые соответствуют глобу в текущем каталоге, то оболочка передает глоб в grep, который правильно его интерпретирует.
Показать ещё 3 комментария
198

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

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

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

  • 1
    Спасибо, это очень полезно для некоторых других сценариев, с которыми я столкнулся.
  • 24
    --exclude-dir доступно не везде. у моего RH box при работе с GNU grep 2.5.1 его нет.
Показать ещё 4 комментария
55

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

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

выполняется с помощью ack как

ack -icl "foo="

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

ack -icl --cpp "foo="
  • 0
    Выглядит хорошо, попробую автономную версию Perl в следующий раз, спасибо.
  • 3
    Хороший звонок, я больше не могу жить без ack.
Показать ещё 2 комментария
32

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

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

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

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

  • 7
    +1 за упоминание точного номера версии; У меня есть grep 2.5.1 и опция exclude-dir недоступна
  • 1
    но --exclude НЕ работает для каталогов.
21

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

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js
  • 3
    Лучше объединить их в список, например: --exclude = {pattern1, pattern2, pattern3}
11

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

export GREP_OPTIONS="--exclude=\*.svn\*"
11

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

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

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

  • 3
    Да, это не работает для меня. Тот, который работал для меня, был: exclude-dir = .svn
  • 2
    @ Николя спасибо! Я рвал на себе волосы о том, почему это не сработает. Скажите, есть ли способ узнать это из справочной страницы? Все, что он говорит, это соответствует «УЗОРУ». РЕДАКТИРОВАТЬ Manpage говорит "файл", как объяснено здесь fixunix.com/unix/…
9

Я считаю grepping grep output очень полезным:

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

Хотя это фактически не останавливает его от поиска двоичных файлов.

  • 10
    Вы можете использовать grep -I для пропуска двоичных файлов.
  • 0
    Я также сделал это, когда я был молодым ... теперь я знаю лучше, и когда сталкиваюсь с проблемой, первым делом это RTFM
7

В CentOS 6.6/Grep 2.6.3 я должен использовать его следующим образом:

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

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

5

Если вы не прочь использовать 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
5

Я дилетант, предоставленный, но вот как выглядит мой ~/.bash_profile:

export GREP_OPTIONS="-orl --exclude-dir=.svn --exclude-dir=.cache --color=auto" GREP_COLOR='1;32'

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

3

Попробуйте следующее:

 $ find . -name "*.txt" -type f -print | xargs file | grep "foo=" | cut -d: -f1

Основано здесь: http://www.unix.com/shell-programming-scripting/42573-search-files-excluding-binary-files.html

  • 3
    Это не работает с именами файлов с пробелами, но эту проблему легко решить, используя print0 вместо print и добавив опцию -0 в xargs.
2

Посмотрите @этот.

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
  • 2
    Вещи, которые достигают приблизительно этого, были рассмотрены в других сообщениях; более того, это неправильно, так как при различных настройках макета он будет портить номера строк и тому подобное или исключать нужные строки контекста.
  • 0
    как вы можете использовать несколько опций "-v" одновременно?
2

эти сценарии не выполняют всю проблему... Попробуйте это лучше:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

этот script настолько лучше, потому что он использует "реальные" регулярные выражения, чтобы избежать каталогов из поиска. просто выделите папки или имена файлов с помощью "\ |" на grep -v

наслаждайся этим! найденный на моей оболочке Linux! XD

2

Найти и xargs - ваши друзья. Используйте их для фильтрации списка файлов, а не grep --exclude

Попробуйте что-нибудь вроде

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="
  • 1
    Это не работает с именами файлов с пробелами, но эту проблему легко решить, используя print0 вместо print и добавив опцию -0 в xargs.
1

Если вы ищете нерекурсивно, вы можете использовать glop patterns для соответствия именам файлов.

grep "foo" *.{html,txt}

включает html и txt. Он выполняет поиск только в текущем каталоге.

Поиск в подкаталогах:

   grep "foo" */*.{html,txt}

В подкаталогах:

   grep "foo" */*/*.{html,txt}
1

подходит для файла tcsh.alias:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

Пришло время понять, что часть {mm, m, h, cc, c} НЕ должна быть внутри кавычек. ~ Кит

1

Опция --binary-files=without-match для GNU grep позволяет ей пропускать двоичные файлы. (Эквивалентно переключателю -I, указанному в другом месте.)

(Для этого может потребоваться последняя версия grep; 2.5.3 имеет ее, по крайней мере.)

0

Чтобы игнорировать все двоичные результаты из grep

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

Часть awk будет отфильтровывать все двоичные файлы foo совпадений строк

-3

Попробуйте следующее:

  • Создайте папку с именем "--F" под currdir.. (или переместите другую папку там, где она была переименована в "--F", т.е. double-minus-F.
  • #> grep -i --exclude-dir="\-\-F" "pattern" *

Ещё вопросы

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