grep, але лише певні розширення файлів


965

Я працюю над написанням деяких сценаріїв до 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 щодо наявності інструментів, які "роблять одне і роблять це добре". Є ідеально хороший інструмент для пошуку файлів із ДУЖЕ очевидним іменем.
Ед Мортон

Відповіді:


1352

Просто скористайтеся таким --includeпараметром:

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

це має робити те, що ти хочеш.

Щоб отримати пояснення з відповіді HoldOffHunger нижче:

  • grep: команда

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

  • -i: ігнор-випадок

  • --include \*.cpp: all * .cpp: файли C ++ (бігти з \ на випадок, якщо у назви файлів є каталог із зірочками)

  • ./: Почніть з поточного каталогу.


123
Для запису: -r (рекурсивний) -i (ігнор-випадок) --включити (шукати лише файли, які відповідають шаблону файлів)
Луїс

34
Можна додатково оптимізувати доgrep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345]
zwol

1
@Hong, де документація, що -R призначена для символічних посилань?
тит

8
Цей приклад, мабуть, має високий бал, оскільки він охоплює такий широкий спектр можливостей, але відповідь, наведена нижче від grep -r --include = *. Txt 'searchterm' ./, дійсно пояснює суть відповіді
Девід Каспер

10
чому б не використовувати подвійні лапки замість зворотної косої риси? напр .:grep -r -i --include="*.h" --include="*.cpp" CP_Image
памбда

283

Деякі з цих відповідей виглядали занадто синтаксичними, або вони викликали проблеми на моєму сервері Debian. Це прекрасно працювало для мене:

PHP Revolution: Як зібрати файли в Linux, але лише певні розширення файлів?

А саме:

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

... або нечутлива до регістру версія ...

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

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

  • -i: ігнор-випадок

  • --include: all * .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 "якусь ріпку" - включити = *. {module, inc, c, h} *
ashish

3
Гарна відповідь. Чистіше, ніж прийнято в IMO, але слід додати критерії пошуку, як зауважив
@ashish

чому --includeваріант після голки, а не з іншими варіантами?
vladkras

@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
nullrevolution

використовувати з додатковим "-типом f", щоб ігнорувати всі об'єкти каталогів, цікавлять лише файли.
kensai

1
Я використовував цей метод протягом багатьох років, і він працює, але він набагато повільніше рекурсивного grep, оскільки exec find породжує окремий процес grep для кожного файлу, який потрібно шукати.
beaudet

Звертаючись до коментаря @ 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грепу.
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_
оставити

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 -імені"

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.