як я можу використовувати опцію grep --include для декількох типів файлів?


98

Коли я хочу зібрати всі HTML-файли в деякому каталозі, я виконую наступне

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

яка добре працює. Проблема полягає в тому, як зібрати всі html, htm, php-файли в деякому каталозі?

З цього пункту Використовуйте grep --exclude / - включайте синтаксис, щоб не проглядати певні файли , здається, що я можу зробити наступне

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

Але, на жаль, це не спрацювало б для мене.
FYI, моя греп-версія - 2.5.1.

Відповіді:


137

Можна використовувати кілька --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 . Його часто можна використовувати як замінник xargs. Це також варто швидко прочитати. HTH.
Стів

3
@tianyapiaozi: Ви правильні, що котирування навколо розширення дужки - це проблема; без цитування, однак, *все ще підлягає глобулюванню, як частина вбудованого маркера, у цьому випадку просто не відбувається нічого, тому що відповідатимуть лише файли, буквально названі щось подібне --include=foo.html. Для безпечності процитуйте *(що ви можете зробити індивідуально \*). Як додатковий бонус, це робить візуально зрозумілішим, що не оболонка, яка повинна виконувати глобулінг у цьому випадку.
mklement0

2
Що стосується findрішення: використання -exec grep "pattern" {} +замість | xargs grep "pattern"є більш надійним (наприклад, обробляє назви файлів з пробілами), а також більш ефективним.
mklement0

32

Використання {html,php,htm}може працювати тільки в якості розширення розпірки , яка є нестандартною (НЕ POSIX-сумісної) особливістю bash, kshі zsh.

  • Іншими словами: не намагайтеся використовувати його у скрипті, на який націлено, /bin/sh- у цьому випадку використовуйте явні численні --includeаргументи.

  • grepсама по собі не розуміє {...}позначення.

Щоб розпізнавання дужок було розпізнане, воно повинно бути без котирування (частиною а) маркера в командному рядку.

Розширення дужки розширюється на декілька аргументів , тож у випадку, коли під рукою ви 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'}


1
Дуже дякую за цю публікацію. Чудові пости не лише відповідають на питання, але навчають вас чомусь новому! Це особливо корисно для тих, хто пише нас на чомусь, що повинно відповідати POSIX. Усі, хто використовує Mac OS X, повинні зазирнути сюди!
сабалаба

@sabalaba: Я радий це почути, але щоб було зрозуміло: хоча розширення дужок не сумісне з POSIX, воно працює з bashбудь-якою платформою, на якій bashпрацює.
mklement0

9

Спробуйте видалити подвійні лапки

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

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

Це найкраща відповідь, особливо для мене, і я думаю, що ви можете поставити -rsn замість -r -s -n (але це нитко).
стрункий

Зазвичай я використовую -rns . Для наочності в прикладі я мав зазначити -r -n -s :-) Радий, що це допомогло.
Прадіп

Рекомендую додати -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варіанти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.