複数のファイルタイプにgrep --includeオプションを使用するにはどうすればよいですか?


98

一部のディレクトリにあるすべてのhtmlファイルをgrepしたい場合は、次のようにします

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

うまくいきます。問題は、いくつかのディレクトリにあるすべてのhtml、htm、phpファイルをgrepする方法です。

これから、特定のファイルをgrepしないようにgrep --exclude /-include構文を使用して、次のようにできるようです

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

しかし残念なことに、それは私にはうまくいきませんでした。
ちなみに、私のgrepバージョンは2.5.1です。

回答:


136

複数の--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が処理するよりも多くのファイルを処理しています。
James Moore

2
@JamesMoore:GNU Parallelを見てください。多くの場合、の代替として使用できxargsます。これも一読する価値があります。HTH。
Steve

3
@tianyapiaozi:中括弧の展開に関する引用が問題であることは間違いありません。引用なし、しかし、*まだグロブの対象となり、それが中に埋め込まれたトークンの一部として、それだけで起こるファイルのみので、この場合には何も一致しない文字通りの名前のようなものが--include=foo.html一致します。安全のために、*(で個別に実行できる)を引用してください\*。追加のボーナスとして、この場合、グロビングを実行するシェルではないことが視覚的に明確になります。
mklement0

2
find解決策として:の-exec grep "pattern" {} +代わりにを使用すると、| xargs grep "pattern"より堅牢になり(スペースを含むファイル名を処理するなど)、効率が向上します。
mklement0

32

使い方{html,php,htm}としてのみ働くことができるブレース展開非標準の(POSIXに準拠していない)機能で、bashksh、と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'}


1
この投稿をありがとうございました。素晴らしい投稿は質問に答えるだけでなく、何か新しいことを教えてくれます!これは、POSIX準拠である必要がある何かを書いている私たちにとって特に便利です。Mac OS Xを使用している方は、こちらをご覧ください。
サバラバ2017年

@sabalaba:私はそれを聞いてうれしいですが、明確にする必要があります。ブレースの展開はPOSIXに準拠していませんが、それbashbash実行されるすべてのプラットフォームで動作します。
mklement0 2017年

9

二重引用符を削除してみてください

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

@tianyapiaozi試してくださいgrep --include=\*.{html,php,htm} pattern -R /some/path。それは私のために働いた。
Hyunjun Kim

4

これは機能していませんか?

  grep pattern  /some/path/*.{html,php,htm} 

あんまり。ファイルはサブディレクトリのサブディレクトリに存在する可能性があります
tianyapiaozi

2

これを試して。-rは再帰検索を行います。-sは、ファイルが見つからないというエラーを抑制します。-nは、パターンが見つかったファイルの行番号を表示します。

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}

これは特に私にとって最良の答えであり、-r -s -nの代わりに-rsnを使用できると思います(ただし、それは問題です)。
スリム

通常は-rnsを使用します。例を明確にするために、私は-r -n -s :-) に言及する必要がありました。
Pradeep

-I標準セットに追加することをお勧めします。(ほとんど検索されない)バイナリファイルをスキップするため、効率が向上します。その後、我々は行くgrep -rIns ...acousticly :)うまく果たしている
流血の

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あまりにもオプション。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.