Используйте синтаксис grep --exclude/- include, чтобы не просматривать определенные файлы
Я ищу строку 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 или предлагаемый поиск).
22 ответа
Используйте синтаксис оболочки:
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
что, скорее всего, не то, что вы хотели.
Если вы просто хотите пропустить двоичные файлы, я предлагаю вам посмотреть на -I
(верхний регистр я) вариант. Он игнорирует двоичные файлы. Я регулярно использую следующую команду:
grep -rI --exclude-dir="\.svn" "pattern" *
Он ищет рекурсивно, игнорирует двоичные файлы и не ищет в скрытых папках Subversion какой-либо шаблон, который мне нужен. Я имею псевдоним как "grepsvn" на моей коробке на работе.
Пожалуйста, обратите внимание на ack, который предназначен именно для этих ситуаций. Ваш пример
grep -ircl --exclude=*.{png,jpg} "foo=" *
делается с Ack как
ack -icl "foo="
потому что ack никогда не просматривает двоичные файлы по умолчанию, а -r включен по умолчанию. И если вы хотите только файлы CPP и H, то просто сделайте
ack -icl --cpp "foo="
grep 2.5.3 ввел параметр --exclude-dir, который будет работать так, как вы хотите.
grep -rI --exclude-dir=\.svn PATTERN .
Вы также можете установить переменную окружения: GREP_OPTIONS="-exclude-dir=.svn"
Я второй голос Andy Lester за кв, хотя, это лучший.
Я обнаружил, что после долгого времени вы можете добавить несколько включений и исключений, таких как:
grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js
Предлагаемая команда:
grep -Ir --exclude="*\.svn*" "pattern" *
концептуально неверно, потому что --exclude работает с базовым именем. Другими словами, он пропустит только.svn в текущем каталоге.
В grep 2.5.1 вы должны добавить эту строку в профиль ~/.bashrc или ~ /.bash
export GREP_OPTIONS="--exclude=\*.svn\*"
Я считаю, что вывод grep иногда очень полезен:
grep -rn "foo=" . | grep -v "Binary file"
Тем не менее, это на самом деле не мешает искать двоичные файлы.
На CentOS 6.6/Grep 2.6.3 я должен использовать его так:
grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"
Обратите внимание на отсутствие знака равенства "=" (в противном случае --include
, --exclude
, include-dir
а также --exclude-dir
игнорируются)
Если вы не против использования 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
git grep
использование git grep
который оптимизирован для производительности и направлен на поиск по определенным файлам.
По умолчанию он игнорирует двоичные файлы и выполняет ваши .gitignore
, Если вы не работаете со структурой Git, вы все равно можете использовать ее, передав --no-index
,
Пример синтаксиса:
git grep --no-index "some_pattern"
Дополнительные примеры см.:
Конечно, я дилетант, но вот как выглядит мой ~/.bash_profile:
export GREP_OPTIONS = "- orl --exclude-dir =.svn --exclude-dir =.cache --color = auto" GREP_COLOR = '1; 32'
Обратите внимание, что для исключения двух каталогов мне пришлось дважды использовать --exclude-dir.
В каталогах также много бинарных файлов. Я не могу искать только определенные каталоги (структура каталогов - большой беспорядок). Есть ли лучший способ поиска только в определенных файлах?
ripgrep
Это один из самых быстрых инструментов, предназначенных для рекурсивного поиска в текущем каталоге. Он написан на Rust и построен на основе движка Rust для обеспечения максимальной эффективности. Проверьте подробный анализ здесь.
Так что вы можете просто запустить:
rg "some_pattern"
Это уважение вашего .gitignore
и автоматически пропустить скрытые файлы / каталоги и двоичные файлы.
Вы по-прежнему можете настраивать включение или исключение файлов и каталогов, используя -g
/ --glob
, Глобальные правила соответствуют .gitignore
шарики. Проверьте man rg
за помощью.
Дополнительные примеры см.: Как исключить некоторые файлы, не соответствующие определенным расширениям, с помощью grep?
На macOS вы можете установить через brew install ripgrep
,
Если вы ищете не рекурсивно, вы можете использовать шаблоны glop для соответствия именам файлов.
grep "foo" *.{html,txt}
включает в себя HTML и TXT. Он ищет только в текущем каталоге.
Для поиска в подкаталогах:
grep "foo" */*.{html,txt}
В подкаталогах:
grep "foo" */*/*.{html,txt}
Найди и xargs твои друзья. Используйте их для фильтрации списка файлов, а не grep --exclude
Попробуйте что-то вроде
find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="
Попробуй это:
$ найти. -name "*.txt" -type f -print | файл xargs | grep "foo=" | cut -d: -f1
Основан здесь: http://www.unix.com/shell-programming-scripting/42573-search-files-excluding-binary-files.html
Эти сценарии не решают всех проблем... Попробуйте это лучше:
du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"
этот скрипт настолько лучше, потому что он использует "настоящие" регулярные выражения, чтобы избежать поиска каталогов. просто отдельные имена папок или файлов с помощью "\|" на grep -v
наслаждайся этим! нашел на моей оболочке linux! XD
Смотри @ этот.
grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
Подходит для tcsh .alias файла:
alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'
Мне понадобилось время, чтобы понять, что часть {mm,m,h,cc,c} НЕ должна быть внутри кавычек. ~Keith
--binary-files=without-match
вариант для GNU grep
получает пропустить двоичные файлы. (Эквивалентно -I
Переключатель упоминается в другом месте.)
(Для этого может потребоваться последняя версия grep
; 2.5.3 есть, как минимум.)
Чтобы игнорировать все двоичные результаты от grep
grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'
Часть awk отфильтрует все строки двоичного файла foo match
Попробуй это:
- Создать папку с именем "
--F
"под currdir ..(или ссылка на другую папку там переименована в"--F
то естьdouble-minus-F
, #> grep -i --exclude-dir="\-\-F" "pattern" *