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': Что искать

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


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}
#                      ^^^^^^^^^^^^^^^^^^^


3

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

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

так

ag -G *.h -G *.cpp CP_Image <path>

используя 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' показывает имя файла и строку.


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"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.