как использовать параметр grep --include для нескольких типов файлов?

98

Когда я хочу получить все html-файлы в каком-либо каталоге, я делаю следующее

grep --include="*.html" pattern -R /some/path

что хорошо работает. Проблема в том, как выполнить поиск всех файлов html, htm, php в каком-либо каталоге?

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

grep --include="*.{html,php,htm}" pattern -R /some/path

Но, к сожалению, у меня это не сработало.
К вашему сведению, моя версия grep - 2.5.1.

Тианьяпиози
источник

Ответы:

140

Вы можете использовать несколько --includeфлагов. Это работает для меня:

grep -r --include=*.html --include=*.php --include=*.htm "pattern" /some/path/

Однако вы можете поступить так, как было Deruijterпредложено. Это работает для меня:

grep -r --include=*.{html,php,htm} "pattern" /some/path/

Не забывайте, что вы можете использовать findи xargsдля такого рода вещей:

find /some/path/ -name "*.htm*" -or -name "*.php" | xargs grep "pattern"

HTH

Стив
источник
1
Я вижу проблему. Я использовал --include = " . {Html, php}", чтобы предотвратить расширение оболочки » , что в то же время не позволяет оболочке расширять {html, php}. Кажется, что знак равенства в --include = * может предотвратить расширение оболочки '*'.
tianyapiaozi
xargs на самом деле не заменяет; очень часто, когда вам нужна эта функция, вы имеете дело с большим количеством файлов, чем может обработать xargs.
Джеймс Мур,
2
@JamesMoore: Взгляните на GNU Parallel . Его часто можно использовать как замену xargs. Это также стоит быстро прочитать. HTH.
Стив
3
@tianyapiaozi: Вы правы, что цитата вокруг фигурных скобок является проблемой; без квотирование, однако, *по - прежнему подлежит универсализации как часть маркера он встроен в , это просто происходит не матч ничего в этом случае, потому что только те файлы , в буквальном смысле под названием что - то вроде --include=foo.htmlбы совпадают. На всякий случай процитируйте *(что вы можете сделать индивидуально \*). В качестве дополнительного бонуса это делает визуально более понятным, что в данном случае подстановка должна выполняться не оболочкой .
mklement0
2
Что касается findрешения: использование -exec grep "pattern" {} +вместо | xargs grep "pattern"более надежно (например, обрабатывает имена файлов с пробелами), а также более эффективно.
мклемент0
32

Использование {html,php,htm}может работать только в качестве расширения распорки , которая является нестандартной (не POSIX-совместимой) особенностью bash, kshи zsh.

  • Другими словами: не пытайтесь использовать его в сценарии, который нацелен /bin/sh- в этом случае используйте явные множественные --includeаргументы.

  • grepсам не понимает {...}обозначений.

Чтобы раскрытие фигурных скобок было распознано, это должен быть токен без кавычек (часть a) в командной строке.

Расширение скобки расширяется до нескольких аргументов , поэтому в рассматриваемом случаеgrepотображается несколько --include=... параметров, как если бы вы передали их по отдельности.

Результаты расширения скобки: подвергаются подстановке (расширению имени файла) , что имеет подводные камни :

  • Каждый результирующий аргумент может быть расширен до совпадающих имен файлов, если он содержит не заключенные в кавычки метасимволы подстановки, такие как *.
    Хотя это маловероятно с такими токенами, как --include=*.html(например, у вас должен быть файл, буквально названный чем-то вроде --include=foo.htmlдля чего-то сопоставимого), в целом об этом стоит помнить.

  • Если nullglobопция оболочки shopt -s nullglobвключена ( ) и подстановка совпадает ничего не соответствует , аргумент будет отброшен .

Следовательно, для полностью надежного решения используйте следующее:

grep -R '--include=*.'{html,php,htm} pattern /some/path
  • '--include=*.'рассматривается как буквальный , так в одинарные кавычки ; это предотвращает случайную интерпретацию *символа подстановки.

  • {html,php,htm}, - по необходимости - расширение фигурных скобок без кавычек [1] , расширяется до 3 аргументов, которые из-за {...} прямого следования за '...'токеном , включают в себя , что маркер.

  • Следовательно, после удаления кавычек оболочкой в конечном итоге передаются следующие 3 буквальных аргументаgrep :

    • --include=*.html
    • --include=*.php
    • --include=*.htm

[1] Точнее, только релевантные синтаксису части раскрытия фигурных скобок должны быть не заключены в кавычки, элементы списка могут по-прежнему заключаться в индивидуальные кавычки и должны быть, если они содержат метасимволы подстановки, которые могут привести к нежелательному подстановке подстановки после раскрытия фигурных скобок; хотя в данном случае это и не обязательно, приведенное выше можно записать как
'--include=*.'{'html','php','htm'}

mklement0
источник
1
Большое спасибо за этот пост. Отличные посты не только отвечают на вопрос, но и учат чему-то новому! Это особенно полезно для тех из нас, кто пишет о том, что должно быть совместимо с POSIX. Любой, кто использует Mac OS X, должен посмотреть здесь!
sabalaba
@sabalaba: Я рад это слышать, но для ясности: хотя расширение скобок не совместимо с POSIX, оно работает bashна любой платформе, на которой bashработает.
mklement0 04
9

Попробуйте удалить двойные кавычки

grep --include=*.{html,php,htm} pattern -R /some/path
Deruijter
источник
1
@tianyapiaozi Попробуй grep --include=\*.{html,php,htm} pattern -R /some/path. У меня это сработало.
Хёнджун Ким
4

это не работает?

  grep pattern  /some/path/*.{html,php,htm} 
Виджай
источник
На самом деле, нет. Файлы могут находиться в подкаталоге подкаталога
tianyapiaozi
2

Попробуй это. -r выполнит рекурсивный поиск. -s подавляет ошибки "файл не найден". -n покажет вам номер строки файла, в котором найден шаблон.

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}
Pradeep
источник
Это, в частности, лучший ответ для меня, и я думаю, вы можете поставить -rsn вместо -r -s -n (но это придирки).
slim
Обычно я использую -rns . Для ясности в примере мне пришлось упомянуть -r -n -s :-) Рад, что это помогло.
Pradeep
Рекомендую добавить -Iв стандартный набор. Он пропускает двоичные файлы (которые почти никогда не просматриваются), что повышает эффективность. Затем мы идем, grep -rIns ...который акустически красиво играет :)
кровавый
2

Он работает с той же целью, но без --includeдополнительных возможностей. Он также работает с grep 2.5.1.

grep -v -E ".*\.(html|htm|php)"
Кохеи Миками
источник
0

Использовать grepс findкомандой

find /some/path -name '*.html' -o -name '*.htm' -o -name '*.php' -type f 
 -exec grep PATTERN {} \+

Вы также можете использовать -regexи -regextypeпараметры.

Принц Джон Уэсли
источник