bash – “find” を使って特定のファイル名を無視するには?

bash find regex

私の好きなbashコマンドの一つです

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

これは、カレントディレクトリ以下のすべてのファイルの内容を指定された SearchString で検索することができます。開発者としては、これが便利なこともあります

しかし、私の現在のプロジェクトと私のコードベースの構造のために、このBASHコマンドをより高度なものにしたいと思っており、”.svn “を含むディレクトリ以下のファイルや”.html “で終わるファイルを検索しないようにしています

findのmanページはちょっと混乱しました。私は -prune を使ってみましたが、奇妙な動作をしました。.htmlページだけをスキップしようとして(最初に)、.htmlページだけをスキップしてみました

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

を使ってみて、期待していた挙動が得られませんでした。私は-pruneの意味を見落としているかもしれません。皆さん教えてもらえませんか?

Thanks

  154  Cody S  2012-03-05


ベストアンサー

find の否定 (!) 機能を使って、特定の名前のファイルにマッチしないようにすることができます

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

そのため、名前の末尾が.htmlで終わっていたり、パスのどこかに.svnが含まれていたりすると、一致しないのでexecは実行されません

222  Paul  2012-03-06


私も以前から同じ問題を抱えていましたが、状況に応じて適用できる解決策がいくつかあります

  • ack-grepは、デフォルトではバージョン管理ディレクトリや一時ファイルをスキップする「開発者のgrep」のようなものです。man のページでは、特定のファイルタイプのみを検索する方法と、独自のを定義する方法が説明されています
  • grep 自身の --exclude および --exclude-dir オプションは、ファイルのグロブや単一のディレクトリをスキップするために非常に簡単に使うことができます (残念ながら、ディレクトリのグロブはありません)
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ...はうまくいくはずですが、長い目で見ると上記のオプションの方が手間が少ないかもしれません

12  l0b0  2012-03-06


以下のfindコマンドは、ディレクトリ名に.svnが含まれるディレクトリのプルーンを行いますが、ディレクトリ内には降りませんが、プルーンされたパス名が表示されます・・・(-name '*.svn'が原因です!)

ディレクトリ名をフィルタリングすることができます。grep -d skip は、このような “ディレクトリ名 “の入力を黙ってスキップします

GNU grepでは、/dev/nullの代わりに-Hを使うことができます。ちょっとした余談ですが、\+\;よりもずっと速くなります。\+\;よりもはるかに速いことがあります。例えば、100万個の一行ファイルでは、\;を使うと4m20秒かかりましたが、\+を使うと1.2秒しかかかりませんでした

以下のメソッドは、-execの代わりにxargsを使用し、ファイル名に改行\nがないことを前提としています。ここで使われる xargs は find の \+ とほとんど同じです

xargsは、-dオプションで入力デリミタを'\n'に変更することで、連続したスペースを含むファイル名を渡すことができます

これは、名前に .svn を含むディレクトリを除外し、.html で終わらないファイルのみを greps します

find . \( -name '*.svn*' -prune  -o ! -name '*.html' \) |
xargs -d '\n' grep -Hd skip 'SearchString'

9  Peter.O  2012-03-06


この例では、名前に “test “が含まれるファイルを検索対象から除外しています。検索自体は、XMLファイルのみを対象に “ProductReplacement “を検索します

find . ! -name '*test*.*' -name '*.xml' -exec grep -i 'ProductReplacement' {} \; -print

追加で、より多くの除外パターンを指定することができます

!-name ‘file_pattern’ entries

0  George Smith  2020-06-03


タイトルとURLをコピーしました