Dir.globコメコメをつかったワンライナー


Rubyで、Dir.glob('**/*')と書くと、ディレクトリ(フォルダー)の中身を再帰的にたどって配列に格納してくれてたいへん便利です。これを使って、ファイル名の一部を正規表現(Regular Expression)で指定して、深いところにあるファイルを探し出すワンライナーが書けるのではないかと思いつきました。


さて、いろいろ問題がありそうなのは、Dir.glob('**/*')という表記にせよ、正規表現にせよ、コマンドプロンプトやシェルで展開されしまわないようにエラーにならないように考えなければいけない。


試行錯誤中・・・


できた!

ruby -e'for filename in Dir.glob("**/*") do puts filename if filename =~ /this/; end'


えっと、これは「リカーシブ(再帰的)にすべてのファイル名を調べ、そのファイル名(パスを含む)がthisを含む場合、そのファイル名を表示する」と読みます。もっと改善できるかもしれないけど、今回のポイントは「eahc」を使っていないこと。eachをつかったワンライナー

ruby -e 'Dir["**/*.html"].each {|f| puts f }'

というのがどこかで紹介されていたけど、少なくともDOS窓コマンドプロンプトでは|f|がエラーになってしまいますので不可。


次に改善したい点:正規表現との比較対象にパスを含まないようにする。ファイル名だけとする。


これもできてしまった。エライ!


ruby -e'for filename in Dir.glob("**/*") do puts filename if filename.split("/").last =~ /this/; end'


「リカーシブ(再帰的)に(カレントディレクトリー以下の)すべてのファイル名を調べ(配列に格納し)、そのファイル名(パスを含む)をスラッシュで切り分けて(配列に格納し)その最後(last)がthisを含む場合(正規表現での比較結果が真の場合)、そのファイル名を表示する」


これでホントにfindが不要になったかな?

for filename in Dir.glob("**/*") do 
  puts filename if filename.split("/").last =~ "this"; 
end

コメコメスラッシュコメが覚えなければいけない点で、それ以外は覚えなくて大丈夫。だれかがRubyは記憶力が最低の人用と言っていたけど、そのとおりですね。for filename inという言い回しは、Basicで言う、for i = 1 to 10より汎用性があるから覚えやすいけど、rubyではeachしか使わないという人が居そうです。split("/")は思いつかない人はいないと思うけど"last"は特殊かもしれない。普遍的に書くのなら[-1]の方がいいかもね。私はLISPから来たからlastと書いて思うような結果になっただけ。

今回は気持ちの良い仕上がりでした。


以上