「検索」を使用して特定のファイル名を無視する方法は?


143

私のお気に入りのBASHコマンドの1つは次のとおりです。

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

指定されたSearchStringの現在のディレクトリ以下のすべてのファイルのコンテンツを検索します。開発者として、これは時々便利になりました。

しかし、現在のプロジェクトとコードベースの構造により、「。svn」を含むディレクトリ内またはその下にあるファイルや、 「.html」で終わる

findのMANページは、私を混乱させました。-pruneを使用してみましたが、奇妙な動作をしました。.htmlページのみをスキップしようとして(開始するため)、私は試しました:

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

そして、私が望んでいた行動を得られませんでした。-pruneのポイントを見逃しているのではないかと思います。助けてくれませんか?

ありがとう


1
ただfyi:ビルトインfindbashコマンドではなく、別個のプログラム
— WakiMiko

1
grep -rl 'SearchString'
— -emanuele

@emanueleこんにちは、SuperUser(およびStack Exchangeネットワーク)へようこそ。これは私が尋ねた質問であり、2年半前に答えられました。通常、質問への回答を追加する場合は、コメントではなく下にスクロールして回答してください。この質問には既に承認済みの回答(緑色のチェックマークが付いているもの)があるため、回答に大きな注目が集まる可能性は低いです。ご参考までに。
— コーディS 14年

1
こんにちは、あなたの質問に対する答えではありません。findファイル内の検索に使用する前文で述べたように、これは単なるヒントです。
— エマヌエーレ14

2
FWIWは、すべてのファイルを-name '*.*'検索しません。名前にa が含まれるファイルのみを使用します(通常、使用するのはDOS主義ですが、Unixでは通常そのために使用します)。それらをすべて一致させるには、引数を完全に削除します:。または、grepをファイルにのみ適用する(およびディレクトリをスキップする)場合は、実行します。.*.**find . -exec ...find . -type f -exec ...
— ステファン

回答:


197

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

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

そのため、名前が.htmlで終わるか、パスのどこかに.svnが含まれる場合、名前は一致しないため、execは実行されません。


1
それでも-name 'を指定する必要があります。'そこのどこか?私は否定の前に、または否定の後にそれをしますか?
— コーディS

を*.*含むファイルのみに一致することを保証するという一致の意図はありました.か?が存在しない場合にすべてのファイルと一致します検索nameディレクティブので、上記以外のすべてと一致しますhtmlとのsvn
— ポール・

5
-wholename '*.svn*'むしろ欲しいと思う-name。
— -fuenfundachtzig

2
はい、あります。そのため、.svnディレクトリは検索結果から除外されます。
— -fuenfundachtzig

1
@Noumenon ! -name '.'は.検索結果から除外する必要があります。
— ポール

11

私は長い間同じ問題を抱えていましたが、さまざまな状況に適用できるいくつかの解決策があります:

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

9

次のfindコマンドは、名前にが含まれる ディレクトリを整理します。ディレクトリに.svn降りることはできませんが、整理されたパス名が出力されます...(-name '*.svn'原因です!)..

を介してディレクトリ名を除外することができます。grep -d skipこれにより、そのような入力「ディレクトリ名」が静かにスキップされます。

GNU grepを使用すると、の-H代わりに使用できます/dev/null。ちょっとした副次的な問題として:\+よりもはるかに高速になり\;ます。100万行の1行のファイルの場合、4m20秒\;かかりましたが、使用\+したのは1.2秒だけでした。

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

xargs入力された区切り文字を変更することで、連続したスペースを含むファイル名を渡すことができます'\n'して-dオプションを選択します。

これは、名前のディレクトリ除外含まれているの .svnとで終了していないファイルのみをgrepします.html。

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

1
\+-execアクションのバリアントを指摘していただきありがとうございます。ちょっとした副次的な問題について
— クリスチャンロング14

もちろん、これ+はシェル\にとって特別な文字ではないため、その前に入力する必要はありません。
— スコット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.