web-dev-qa-db-ja.com

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

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

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

私は試した:

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

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

8

それらを削除するために、2番目のgrepにそれを渡すだけです。

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

-vは一致を反転し、パターンに一致しない行を出力します。-Pは、Perl互換の正規表現を有効にして negative lookbehinds を使用できるようにします。この特定の正規表現は.jsに一致しますnotの前にdebugが付いています。これは、(一致を反転しているため).jsファイルのみが印刷されることを意味します。

ただし、@ QuestionOverflowがコメントで指摘しているように、grep -vは出力全体に適用されるだけでなく、出力全体に適用されるため、OKおよびjsを含むlinesを除外するという意図しない副作用が生じる可能性がありますファイル名。それを回避するには、コロンを追加するだけです(これが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を正規表現の最後に追加すると、ファイル名に対してのみ一致し、行の内容とは一致しません。

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

7
terdon

私はfindを使用してファイルを検索し、xargsを介して結果をパイプします。

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

これは、すべてのファイルを検索しますnot*~」、「*.map」または「*.jsに一致しますが、*.debug.js」には一致しません。

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

7
Andreas Wiese

zshを使用すると、次のことができます。

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

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

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

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

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

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

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

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

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

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

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

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

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

--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
1
kenorb