web-dev-qa-db-ja.com

ファイルのリストをgrepに渡す方法

私はfindを使用しており、grepでやりたいファイルのリストを取得しています。そのリストをgrepにパイプするにはどうすればよいですか?

105
MageProspero

まあ、stdoutに書き込むコマンドで機能する一般的なケースは、xargsを使用することです。これにより、コマンドの最後にコマンドライン引数をいくつでも追加できます。

_$ find … | xargs grep 'search'
_

または、コマンドをgrep行にバッククォートまたは$()で埋め込むと、コマンドが実行され、その出力が置き換えられます。

_$ grep 'search' $(find …)
_

これらのコマンドは、ファイル名に空白またはその他の特定の「奇妙な文字」(xargsの場合は_\'"_、$(find …)の場合は_\[*?_)が含まれている場合は機能しません。


ただし、findの特定のケースでは、指定された引数でプログラムを実行する機能が組み込まれています。

_$ find … -exec grep 'search' {} \;
_

_-exec_と_;_の間のすべてが実行するコマンドです。 _{}_は、findで見つかったファイル名に置き換えられます。これにより、ファイルごとに個別のgrepが実行されます。 grepは多くのファイル名を取得してそれらすべてを検索できるため、_;_を_+_に変更して、一致するすべてのファイル名をgrepに一度に渡すように指示できます。

_$ find … -exec grep 'search' {} \+
_
126
Michael Mrozek

grepの一部のバージョン(非組み込みLinuxや [〜#〜] bsd [〜#〜] またはMac OS Xなど)には、再帰的な検索を行う-rオプションがあります。 OpenBSDでは、-Rを使用します(以下の例のように--excludeはありません)。これは、findgrepの単純な組み合わせをカバーしています。

実装に-Rフラグがない場合、またはファイル照合基準をより洗練したい場合は、find-execプライマリを使用して、grepを実行できます。いくつかの古いfind実装は-exec+をサポートしていません。これらのシステムでは、;の代わりに+を使用してください(これにより、ファイルごとに1回grepが呼び出されるため、処理速度は遅くなりますが、それ以外の場合、結果は同じになります)。 /dev/nullトリックは、grepが単一のファイルで呼び出された場合でもファイル名を表示することに注意してください(GNU grepおよびFreeBSD/NetBSD/OSX grepには、同じ効果を得るために-Hオプションがあります)。

find . -type f -name '*.o' -Prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .