2006年02月27日

[Unix] 全てのサブディレクトリをgrep

grepの検索対象のファイルが一つのディレクトリにまとまっているのなら、
grep hoge *.c
で簡単に検索できるんですが、複数のディレクトリに分散している中から探すのに困ってしまいました。
複数ディレクトに分かれていても、ディレクトリの階層がすべて同レベルならば、
grep hoge */*.c
ってできるんですが、階層がまちまちの場合にはこれも使えない。

ということで、findコマンドとの合わせ技を教えてもらいました。
find . -name '*.c' | xargs grep hoge
あるいは、
find . -name '*.c' -exec grep hoge {} /dev/null \;
grepの引数に"/dev/null"が付いているのは、対象ファイルが1つの場合にもファイル名を表示させるため。

【追記】コメントでgrepのみでできる方法を教えて貰いました(fetaroさんありがとうございます)。
grepコマンドに-rというそのものズバリなオプションがありました。
grepの実装にもよるようですが(当時使わされてた環境にはなかったような?)。
grep -r --include=*.c hoge

xargsってコマンドは今回初めて知りましたが、標準入力を元に引数のリストを作成してコマンドを呼んでくれます。
findの-execだと、ファイル毎にgrepコマンドを発行してしまうので、xargsを使う方が速いようだ。

参考:
UNIXの部屋 検索: xargs
http://x68000.q-e-d.net/~68user/unix/pickup?xargs

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/froo/50564541
この記事へのコメント
環境によっては(zshだけ?)、ワイルドカードで「**」ってのが指定できて、ディレクトリを再帰的に展開してくれるらしい。AIXのkshじゃ使えなかったけど。

参考:
http://www-step.kugi.kyoto-u.ac.jp/~futaana/Briefcase/Zsh/wildcard.html
Posted by froo at 2006年03月02日 19:07
もっと簡単にコマンド展開で出来ますね。
grep hoge `find . -name '*.c'`

ただ、あんまりファイル数が多いとコマンドラインの文字数が制限値を超えてエラーになってしまうことがあるらしく、その場合はxargsでやらないとだめなようです。
Posted by froo at 2006年03月04日 12:58
findの-execでやると、grepに渡るファイルの数が1つだけになってしまうためにファイル名が出力されず、どこのファイルにあったのか分かりづらい。なので、必ずファイル名を表示してくれるようにダミーの"/dev/null"を渡すようにしました。
before:
find . -name '*.c' -exec grep hoge {} \;
after:
find . -name '*.c' -exec grep hoge {} /dev/null \;
Posted by froo at 2006年03月07日 12:10
サブフォルダーまで探せて、とても助かりました。
ありがとうございます!(^_^)
Posted by nk at 2012年10月29日 16:44
お使いのgrepのバージョンによりますが、
grepの-rオプションがあれば、再帰的に検索できますよ。
Posted by fetaro at 2014年04月10日 00:56
おお、ありがとうございます。
そうですよねありそうなもんですよね。
なんで当時は-rオプションが見つからなかったのだろうか。
AIXっていう特殊なOSだったからかな?
Posted by 浮浪プログラマ at 2014年04月10日 09:08