ディレクトリの下にあるすべてのファイルをgrepする簡単な方法はありますか?


21

いくつかのコンテンツについてツリー全体を検索したいときは、

find . -type f -print0 | xargs -0 grep <search_string>

パフォーマンスまたは簡潔さの観点からこれを行うより良い方法はありますか?


2
@Downvoter:懸念を共有できる場合は、この質問を改善させていただきます。
ダンクラム

2
多くの検索バージョンにはxargsが組み込まれています:find。-type f -exec fgrep <search_string> {} +
-simpleuser

回答:


42

grepサポート-rオプション(再帰用)かどうかを確認します。

grep -r <search_string> .

1
うん...私はstackoverflow.com/questions/16956810/を見つけました... そしてそれも答えです。
ダンクラム

--exclude-dirパフォーマンスに対処するためのコメントを追加すると、勝者がいます!
ダンクラム

1
これは移植性がないことに注意しgrepてください。ただし、最近のFreeBSDおよびLinuxディストリビューションではサポートされています。そして、なぜ--exclude-dirですか?木全体検索するように依頼しませんでしたか?
フィリポス

公正な点... --exclude-dirは、サブツリーの一部が大きいが役に立たないため、私のユースケースでは実際に便利であり、パフォーマンスについて尋ねました...しかし、あなたは正しい、それは必要ではありません。
ダンクラム

この場合、IIRC --exclude-dirがGNU専用であることを追加する必要がありますgrep。(-:
フィリポス

13

準最適な回答:の出力をfindにパイプする代わりにgrep、単に実行することができます

find . -type f -exec grep 'research' {} '+'

そして出来上がり、2つではなく1つのコマンド!

説明 :

find . -type f

内のすべての通常ファイルを検索します。

-exec grep 'research'

grep '研究'

{}

見つかったファイル名

'+'

ファイル名ごとに1回ではなく、すべてのファイル名ごとに1つのコマンドを使用します。

注:';'ファイル名ごとに1回でした。

それ以外に、それを使用してソースコードを処理する場合ack、コードビットを簡単に検索するために作成されたを調べることができます。

ack

編集:

その研究を少し拡張することができます。まず、-name ''スイッチを使用して、find特定の命名パターンを持つファイルを検索できます。

例えば ​​:

  • ログに対応するファイルのみ: -name '*.log'

  • cヘッダーに対応するファイルのみですが、ファイル名拡張子に大文字または小文字を使用することはできません。 -iname *.c

注:for grepやのように、この場合ack-iスイッチは大文字と小文字を区別しません。

その場合、grepは色と行番号なしで表示されます。

スイッチ--color-nスイッチで変更できます(それぞれファイル内の色と行番号)。

最終的に、次のようなものを持つことができます:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'

例えば

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello

5
ackは素晴らしく、高速版ackag(シルバーサーチャー、geoff.greer.fm / ag
-cfeduke

1
-name '*.log'高速」のようなフィルターを使用することをお勧めします。
sdkks

@cfeduke主にagがWSLのデフォルトのaptリポジトリの一部ではないため、試していません(所有しているもので作業する必要があります!)
Pierre-Antoine Guillaume

秘Aは/ dev / nullをgrepに追加して、ファイル名を表示することです。
ChuckCottrill

トリックは、ディレクトリのみを検索し、次に-exec grep / dev / null {} / *を使用して、ディレクトリごとに単一のfork / execを持つすべてのファイルを取得することです。
ChuckCottrill

12

サブディレクトリに再帰する場合:

grep -R 'pattern' .

この-Rオプションは標準オプションではありませんが、ほとんどの一般的なgrep実装でサポートされています。


7
使用-rの代わりに、-RGNU grepのが関係している時にシンボリックリンクをスキップする
αғsнιη

1
@AFSHINなぜシンボリックリンクをフォローしたくないのですか?
クサラナナンダ

4
@Kusalananda Recursion?現在のGNU grep実装は再帰をキャッチしますが、私は思います。それ以外の場合は、「ツリー」の意味に依存します。
フィリポス

2
@Philippos IMHO、ユーザーをベビーシッターすることは、ツールがgrepすべきことではありません。ユーザーがディレクトリ構造にシンボリックリンクループを持っている場合、それはユーザーの問題です:-)
Kusalananda

3
@Kusalanandaそして、システムがループを提供した場合は?迷子にならなかった/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...(-XIのように私をベビーシッターするツール(「AI」と呼ばれる奇妙な魔法を提供しない限り)。(-;
Philippos

5

上記のように(-rまたは-R希望するシンボリックリンクの処理に応じて)クイックオプションです。

ただし-d <action>、役に立つ場合があります。

良い点-dはskipコマンドです。このコマンドは、現在のレベルをスキャンしたいときに「grep:directory_name:Is a directory」を黙らせます。

$ grep foo * 
grep: q2: Is a directory 
grep: rt: Is a directory 

$ grep -d skip foo *  
$ 

そしてもちろん:

$ grep -d recurse foo * 
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).  
$ 

-d skipあなたがする必要はありませんので、オプションでは、別のスクリプト内部で本当に便利です2> /dev/null。:)


0

多くのファイルを処理している場合、サブフォルダー内のすべてのファイルをgrepするのではなく、検索する必要があるファイルを整理すると、grepの実行が高速になります。

私は時々この形式を使用します:

grep "primary" `find . | grep cpp$`

.その末尾のサブフォルダーにあるすべてのファイルを検索しますcpp。次に、これらのファイルを「プライマリ」用にgrepします。

必要に応じて、これらの結果をさらにgrep呼び出しにパイプすることができます。

grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"

1
backticsは現代の優れた実践ではありません。それらはすべて時代遅れです
クリストファー

1
名前に特殊文字を含むファイルがある場合、これは壊れます。これが現状のままで機能するには特別すぎるためにどれだけ特別なものである必要があるかはわかりませんが、あなたがしていることは、lsの出力を解析するのと同じことです。これも悪いことです。
CVn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.