grep, но только определенные расширения файлов

966

Я работаю над написанием некоторых сценариев для grepопределенных каталогов, но эти каталоги содержат всевозможные типы файлов.

Я хочу grepпросто .hи .cppсейчас, но, возможно, несколько других в будущем.

Пока что у меня есть:

{ grep -r -i CP_Image ~/path1/;

grep -r -i CP_Image ~/path2/;

grep -r -i CP_Image ~/path3/;

grep -r -i CP_Image ~/path4/;

grep -r -i CP_Image ~/path5/;} 

| mailx -s GREP email@domain.com

Может кто-нибудь показать мне, как я бы сейчас добавил только конкретные расширения файлов?

Джейсон
источник
13
Пробовал grep -r -i CP_Image ~/path1/*.{h,cpp}?
8
Используйте Серебряный Searcher : ag -i CP_Image ~/path[1-5] | mailx -s GREP email@domain.com. Работа выполнена.
Johnsyweb
Используйте egrep (скорее всего, он предварительно установлен в вашей системе), а затем вы можете использовать регулярное выражение.
Dogweather
8
Парни из GNU действительно запутались, когда добавили, -rчтобы grepони искали файлы, поскольку это нарушает мантру UNIX о наличии инструментов, которые «делают одно и делают это хорошо». Есть очень хороший инструмент для поиска файлов с ОЧЕНЬ очевидным именем.
Эд Мортон

Ответы:

1355

Просто используйте --includeпараметр, например так:

grep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345] | mailx -s GREP email@domain.com

это должно делать то, что вы хотите.

Чтобы получить объяснение из ответа HoldOffHunger ниже:

  • grep: команда

  • -r: рекурсивно

  • -i: ignore-case

  • --include \*.cpp: все * .cpp: файлы C ++ (экранируйте с \ на всякий случай, если у вас есть каталог со звездочками в именах файлов)

  • ./: Начать с текущего каталога.

нельсон
источник
123
Для записи: -r (рекурсивный) -i (регистр игнорирования) --include (поиск только в файлах, которые соответствуют шаблону файла)
Луис
34
Может быть дополнительно оптимизирован доgrep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345]
zwol
1
@ Где находится документация, что -R для символических ссылок?
Тит
8
Этот пример, кажется, имеет высокий балл, потому что он охватывает такой широкий спектр возможностей, но приведенный ниже ответ grep -r --include = *. Txt 'searchterm' ./ действительно объясняет суть ответа
Дэвид Каспер
10
почему бы не использовать двойные кавычки вместо обратной косой черты? Например:grep -r -i --include="*.h" --include="*.cpp" CP_Image
Памбда
283

Некоторые из этих ответов казались слишком синтаксическими или вызывали проблемы на моем Debian Server. Это отлично сработало для меня:

PHP Revolution: как Grep файлы в Linux, но только с определенными расширениями файлов?

А именно:

grep -r --include=\*.txt 'searchterm' ./

... или версия без учета регистра ...

grep -r -i --include=\*.txt 'searchterm' ./
  • grep: команда

  • -r: рекурсивно

  • -i: ignore-case

  • --include: все * .txt: текстовые файлы (экранируйте \, если у вас есть каталог со звездочками в именах файлов)

  • 'searchterm': Что искать

  • ./: Начать с текущего каталога.

HoldOffHunger
источник
7
Вы должны избежать *использования \*.cppили '*.cpp'. В противном случае он не даст ожидаемого результата, если в рабочем каталоге есть несколько *.txtфайлов.
Мелебиус
@Melebius, не могли бы вы объяснить, почему он нуждается в экранировании - имеет ли это какое-либо отношение к упомянутым вами расширениям CPP или TXT? Или вы просто использовали их в качестве примеров?
Саймон Ист
2
@SimonEast Это расширения, которые используются в этом вопросе и ответе, иначе ничего особенного. Это, вероятно , работать без побега при использовании , --include=<pattern>но важно , чтобы избежать *с --include <pattern>(пробел вместо =) , который чувствует себя очень похоже иначе.
Мелебиус
52
grep -rnw "some thing to grep" --include=*.{module,inc,php,js,css,html,htm} ./
Юрий Малов
источник
3
grep -rn "что-то для grep" --include = *. {module, inc, c, h} *
ashish
3
Хороший ответ. Чище, чем принято в IMO, но вы должны добавить критерии поиска, как отметил
@ashish
почему --includeвариант после иглы, а не с другими вариантами?
vladkras 16.09.16
@vladkras, что ты имеешь в виду иглы? Это --?
бесконечность
50

Как насчет:

find . -name '*.h' -o -name '*.cpp' -exec grep "CP_Image" {} \; -print
Амир Афганский
источник
5
Я бы предложил сгруппировать эти -nameаргументы. странные вещи могут случиться, если вы этого не сделаете. find . \( -name '*.h' -o -name '*.cpp' \) -exec grep "CP_Image" {} \; -print
ноль революция
используйте с дополнительным «-type f», чтобы игнорировать все объекты каталога, интересующие только файлы.
Кенсай
1
Я использовал этот метод в течение многих лет, и он работает, но он НАМНОГО медленнее, чем рекурсивный grep, так как exec find запускает отдельный процесс grep для каждого файла, который нужно искать.
Боде
Обращаясь к комментарию @ beaudet, findможно дополнительно связывать аргументы, сводя к минимуму количество вызовов вызываемого процесса. find . \( -name \*.h -o -name \*.cpp \) -exec grep -H CP_Image {} + Это предложено, но не выделено в ответе @ fedorqui ниже и является значительным улучшением. -HАргумент Grep здесь полезен , когда найти только идентифицирует один файл соответствия. Это может исключить использование -printв ответе. Если ваш общий список файлов достаточно мал, {path1,path2}/**/*.{cpp,h}предпочтительнее использовать рекурсивный глобус оболочки (например, ).
Малкольм
19

На серверах HP и Sun опция -r отсутствует, этот способ помог мне на моем сервере HP

find . -name "*.c" | xargs grep -i "my great text"

-i для поиска строки без учета регистра

Сэм Б
источник
1
Я сталкивался с несколькими серверами для веб-хостинговых компаний, у которых нет опции --include, доступной для fgrep, и это командная строка, которую я использую в этих случаях.
Боргбой
Опция --include также недоступна при использовании Git для Windows (MinGW / MSys).
Даррен Льюис
@DarrenLewis доступен в Git Bash для Windows. Но как ни странно, он добавляет красочные псевдонимы, llно не добавляет --color=autoк grep.
Xeverous
Это должен быть принятый ответ для полноты, переносимости и краткости!
Грант Фостер
12

Так как это вопрос поиска файлов, давайте использовать find!

Использование GNU найти можно использовать -regexопцию , чтобы найти эти файлы в дереве каталогов , чье расширение либо .hили .cpp:

find -type f -regex ".*\.\(h\|cpp\)"
#            ^^^^^^^^^^^^^^^^^^^^^^^

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

find -type f -regex ".*\.\(h\|cpp\)" -exec grep "your pattern" {} +

Если у вас нет этого распределения находок, вы должны использовать подход, подобный подходу Амира Афгани , с помощью которого -oобъединяются варианты ( имя заканчивается либо на, .hлибо на.cpp ):

find -type f \( -name '*.h' -o -name '*.cpp' \) -exec grep "your pattern" {} +
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

И если вы действительно хотите использовать grep, следуйте синтаксису, указанному для --include:

grep "your pattern" -r --include=*.{cpp,h}
#                      ^^^^^^^^^^^^^^^^^^^
Федорки "ТАК прекратить вредить"
источник
7

Самый простой способ

find . -type  f -name '*.extension' | xargs grep -i string 
user3640130
источник
3

ag (Серебряный искатель) имеет довольно простой синтаксис для этого

       -G --file-search-regex PATTERN
          Only search files whose names match PATTERN.

так

ag -G *.h -G *.cpp CP_Image <path>
Eldamir
источник
используя ag 2.2.0, мне нужно было поставить свои флаги последними:ag _string_to_find_ -G _filename_regex_
ryanrain
3

Ниже ответ хорош:

grep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345] | mailx -s GREP email@domain.com

Но можно обновить до:

grep -r -i --include \*.{h,cpp} CP_Image ~/path[12345] | mailx -s GREP email@domain.com

Что может быть проще.

хао
источник
1

Следует написать «-exec grep» для каждого «-o -name»

find . -name '*.h' -exec grep -Hn "CP_Image" {} \; -o -name '*.cpp' -exec grep -Hn "CP_Image" {} \;

Или сгруппировать их по ()

find . \( -name '*.h' -o -name '*.cpp' \) -exec grep -Hn "CP_Image" {} \;

опция '-Hn' показывает имя файла и строку.

where23
источник
1

Я знаю, что этот вопрос немного устарел, но я хотел бы поделиться методом, который я обычно использую для поиска файлов .c и .h :

tree -if | grep \\.[ch]\\b | xargs -n 1 grep -H "#include"

или если вам нужен также номер строки:

tree -if | grep \\.[ch]\\b | xargs -n 1 grep -nH "#include"
Том
источник