Ruby には find という標準ライブラリがあるんだけど、Dir.glob と違ってパターン指定できないし、どこで使うの? と思っていた。
が、調べてみると下記のような違いがあるようだ。
-
Dir.glob
は対象となるファイルをすべてリストアップしてから処理を開始する -
Find.find
は見つかったファイルをその都度処理する
大量のファイルがあるディレクトリで、最初のファイルを処理しはじめるまでの時間を計ってみた。
# time ruby -e 'Dir.glob("**/*"){ exit 1 }'
0.46s user 5.34s system 94% cpu 6.125 total
0.47s user 5.45s system 96% cpu 6.136 total
0.48s user 5.49s system 89% cpu 6.634 total
# time ruby -rfind -e 'Find.find("."){ exit 1 }'
0.04s user 0.03s system 94% cpu 0.070 total
0.03s user 0.03s system 95% cpu 0.060 total
0.03s user 0.03s system 94% cpu 0.069 total
Dir.glob
はパターンマッチングしてるのでフェアな比較ではないが、オーダーが違うことがわかる。
すべてのファイルを処理する時間はあまり変わらない (find が若干分が悪い)。
# time ruby -e 'Dir.glob("**/*").to_a'
0.47s user 5.41s system 96% cpu 6.107 total
0.46s user 5.39s system 95% cpu 6.119 total
0.46s user 5.33s system 93% cpu 6.211 total
# time ruby -rfind -e 'Find.find(".").to_a'
1.25s user 5.52s system 94% cpu 7.185 total
1.22s user 5.39s system 96% cpu 6.879 total
1.26s user 5.46s system 96% cpu 7.000 total
使い勝手と総処理時間では Dir.glob のが有利だが、Find は処理を始めるまでの時間が短い (O1) ので、ユーザにすばやいレスポンスを提供することができる。CUI で大量のファイルを処理する場合などはこちらを使ったほうがよいだろう。
ちなみに、Dir.glob
に似たパターンマッチが File.fnmatch
で行えるが {}
や **
が使えず、若干不便なので、正規表現で処理するのが楽。