特定の拡張子に一致しない一部のファイルをgrepで除外するにはどうすればよいですか?


8

単語を含むすべての行をOKディレクトリから再帰的に出力したい。しかし、結果から除外する必要があるいくつかの拡張機能があります。

*~
*.map
*.js except *.debug.js

私は試した:

grep -r --exclude={*~,*.map} "OK" /some/dir

結果からそれらのすべての非デバッグ.jsファイルを削除する方法がわからない場合を除きます。

回答:


7

私はgrepそれらを削除するために1秒だけ通過させます:

grep -r --exclude={\*~,\*.map} "OK" bar/ | grep -vP '(?<!debug)\.js'

-vパターンにマッチしない行印刷、試合を逆転させ-P、私たちが使ってみましょうPerl互換の正規表現できます負lookbehindsを。この特定の正規表現は、一致します.jsされていないことでprececeded debugのみという(私たちは試合を反転しているので)その手段.jsのファイルが印刷されます。

しかし@QuestionOverflowコメントをint指摘したように、それは、フィルタリングの意図しない副作用かもしれないライン含めるOKjsするのでgrep -v出力全体に適用されるだけでなく、ファイル名。これを回避するには、コロンを追加するだけです(これgrepは、ファイル名とファイルの内容を区切るために使用されます)。

grep -r --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js:'

入力行にが含まれているfoo.js:場合、またはファイル名にが含まれて:いる場合は、引き続き失敗します。したがって、確かに、別のアプローチを使用します。

grep -Tr --exclude={*~,*.map} "OK" bar/ | grep -vP '(?<!debug).js\t'

-T原因となるgrepファイル名とファイルの内容との間にタブを印刷します。したがって、単に\t正規表現の末尾にa を追加すると、ファイル名に対してのみ一致し、行の内容とは一致しません。

それでも、使用findすることは関係なくより意味があるかもしれません。


1
必要なファイルの行を誤って除外しますが、両方OKを含み.js、同じ行にありますか?
質問のオーバーフロー

@QuestionOverflowああ、はい、確かに、良いキャッチです。更新された回答を参照してください。
terdon

素晴らしい答え。特にgrepを要求するので、あなたのものを受け入れなければなりません。ありがとう。
質問のオーバーフロー

@QuestionOverflowどういたしまして。ただし、一般的にfindは、この種の場合にはおそらくより適しています。grepあなたが指摘したように、正しいことをするのは難しいかもしれません:)。
terdon

failglobシェルにオプションが設定され ている場合、ソリューションは失敗bash: no match: --exclude=*~ します。たとえば、GLOBパターン引数を引用--excludeして、シェル展開から非表示にする必要があります。たとえば--exclude={\*~,\*.map}
Ian D. Allen

7

findはファイルを見つけて結果をパイプするために使用しますxargs

$ find . -type f \! -name "*~" \
                 \! -name "*.map" \
                 \! \( -name "*.js" -and \! -name "*.debug.js" \) \
         -print0 | xargs -0 grep "OK"

これは、すべてのファイルを検索していない「一致*~」、「*.map」または「*.jsではなく*.debug.js」。

を使用findすると、かなり複雑なルールを簡単に検索できます。このアプローチにより、doubleで発生する可能性があるように、誤って誤検知を削除することがなくなりますgrep


いい答えも:)
質問のオーバーフロー

3
はい、これがおそらく最良の方法です、+ 1。の-exec grep OK {} +代わりに使用してxargs、余分なプログラムを回避することもでき ます。
terdon

2
@IDAllenいいえ、私は推奨し-exec +ないことに注意してください。これは-exec \;、とほとんど同じように、できるだけ少ないコマンドを実行しますxargs
terdon

4

zshあなたが行うことができます。

setopt extendedglob
grep OK some/dir/**/^(*~|*.map|(^*debug).js)

もちろん、引数リストが長すぎない場合は、いつでも実行できます。

printf '%s\0' some/dir/**/^(*~|*.map|(^*debug).js) | xargs -0 grep OK

また、最後の1つだけを作成することもできますzshautoload zargsandzargs some/dir/**/^(*~|*.map|(^*debug).js) -- grep OK
don_crissti

2

出力が順不同で表示されるのを気にしない場合(そうする場合は、並べ替えることができます):

grep -r --exclude={*~,*.map,*.js} "OK" /some/dir **/*.debug.js

これには、シェル**が再帰的グロビングをサポートしている必要がありますshopt -s globstar。zshはデフォルトで実行され、bashは実行後に実行され、ksh93は実行後に実行されますset -o globstar

**シェルでのサポートがなければ、2つのgrepコマンドを使用できます。

grep -r --exclude={*~,*.map,*.js} "OK" /some/dir
grep -r --include=*.debug.js "OK" /some/dir

私のシェルはをサポートしています**が、余分な引数に問題があるため**/*.debug.js、grepがOKディレクトリとして解釈されます。実行してみましたか?
質問のオーバーフロー

@QuestionOverflow私の間違い、私は引数の順序を入れ替えました。
Gilles「SO-邪悪なことをやめる」

2

使用できますripgrep。デフォルトでは、隠しファイルを無視し、ファイルを尊重します.gitignore

次のパラメーターを使用して、包含ルールまたは除外ルールを指定できます。

-g/ --glob GLOB指定したグロブに一致する検索用のファイルとディレクトリを含めるか除外します。

-t/ --type TYPETYPEに一致するファイルのみを検索します。複数のタイプフラグを指定できます。

-T/ --type-not TYPETYPEに一致するファイルを検索しません。

--type-listフラグを使用して、使用可能なすべてのタイプをリストします。

以下にいくつかの簡単な例を示します。

rg -Tjs "OK"                              # Excludes *.js, *.jsx, *.vue files.
rg -tpy "OK"                              # Includes Python files.
rg --type-add 'map:*.map' -tmap PATTERN   # Excludes *.map files.
rg -g '!*.js' -g '*.debug.js' PATTERN     # Excludes *.js apart of *.debug.js.

ここでは除外するための完全なソリューションです*.~*.map*.js、ではありません*.debug.js

rg -g '*.*' -g '!*.~' -g '!*.map' -g '!*.js' -g '*.debug.js' "OK"

テスト:

$ touch file.~ file.map file.js file.debug.js file.txt file.md
$ rg --files
file.debug.js
file.js
file.map
file.md
file.txt
$ rg -g '*.*' -g '!*.~' -g '!*.map' -g '!*.js' -g '*.debug.js' --files
file.debug.js
file.md
file.txt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.