#author("2016-12-16T14:45:15+09:00","default:wikiwriter","wikiwriter") [[Ruby]] #author("2016-12-16T14:47:21+09:00","default:wikiwriter","wikiwriter") &tag(Ruby/ファイルとディレクトリ); *目次 [#c252e0e5] #contents *関連ページ [#c116fb16] *参考情報 [#j7633f1d] -[[Ruby]] *ファイル書き出し[#i1984b49] **BOM付きUTF-8ファイルを書き出す [#i9f1f0fa] -手作業でやるしかない? #pre{{ def write_bom(fp) data = " " data.setbyte(0, 0xEF) data.setbyte(1, 0xBB) data.setbyte(2, 0xBF) fp.write(data) end }} *ファイル検索 [#ra838a88] **Dir::globを使う [#l759e827] *** /tmpに含まれるjpgファイル全てをフルパスの配列として取得する。 [#u976fc5f] -一つの拡張子 p Dir.glob("/tmp/*.jpg") => ["d:/temp/empty.jpg", "d:/temp/ipad.jpg"] -複数の拡張子 Dir.glob("*.{htm,html}") *** globの引数 [#o29f25e8] ワイルドカードを指定できる(正規表現ではない)。 :*|空文字列を含む任意の文字列と一致。 :?|任意の一文字と一致。 :[ ]|括弧内のいずれかの文字と一致。 :{ }|コンマで区切られた文字列の組合せに展開。 :**/|ディレクトリを再帰的にたどってマッチを行う。 **Dir::entriesを使う [#x97c13e8] *** /tmpに含まれるファイル全てを配列として取得する。 [#q384f8b9] p Dir::entries("d:/temp") => [".", "..", "empty.jpg", "ipad.jpg"] 戻り値はファイル名のみ。 *** /tmpに含まれるファイル全てをフルパスの配列として取得する。 [#n3c9237c] dir = "d:/temp/" p Dir.entries(dir).collect{|f| dir + f} => ["d:/temp/.", "d:/temp/..", "d:/temp/empty.jpg", "d:/temp/ipad.jpg"] *** /tmpに含まれるjpgファイル全てをフルパスの配列として取得する [#yf50238d] dir = "d:/temp/" p Dir.entries(dir).grep(/\.jpg$/) {|f| dir + f} => ["d:/temp/empty.jpg", "d:/temp/ipad.jpg"] *** /tmpに含まれるjpg,pngファイル全てをフルパスの配列として取得する [#x54e91b9] grepに渡す正規表現を工夫すればよい。 dir = "d:/temp/" p Dir.entries(dir).grep(/\.(jpg|png)$/) {|f| dir + f} => ["d:/temp/abc.png", "d:/temp/empty.jpg", "d:/temp/ipad.jpg"] *ファイルを削除する [#v4efa279] **FileUtils.rmを使う [#cb4da459] ***ファイルを一つだけ削除 [#ha3bffa3] FileUtils.rm("d:/temp/foo.txt") *** ワイルドカードにマッチするファイルを削除 [#ce50d17a] FileUtils.rm(Dir.glob("d:/temp/*.jpg")) *パスの操作 [#j3f25b5a] **File.expand_pathの第2引数について [#b1dfed6c] -[[RubyのFile.expand_path('相対パス', __FILE__)の意味 - maeharinの日記:http://d.hatena.ne.jp/maeharin/20130104/p1]]。 -File.expand_path('./lib', __FILE__)とすると、"〜a.rb/lib"のように展開される。これはexpand_pathが第二引数がファイル名であろうとそのまま基準ディレクトリとして扱うため。 -ファイル名部分を打ち消すためは、File.expand_path('../lib', __FILE__)とする。 -応用として、testディレクトリにあるテストファイルから、親ディレクトリにある本番rubyスクリプトをrequireするとき次のようにすればよい。"../"の一つは上記のうちけしでつかわれるので二重になっている。 require File.expand_path('../../a.rb', __FILE__) **Pathname [#aff82616] -pathを操作するための専用クラス。 #pre{{ require 'pathname' path = Pathname.new("/tmp") path += 'sample.txt' #結合できる。戻り値はPathnameオブジェクト p path # => #<Pathname:/tmp/sample.txt> }} *Zipファイルの取り扱い [#w58868c9] ** Rubyzipを使用する [#g3416bf2] .zipファイルを圧縮解凍するためのライブラリ。 ***Rubyzipで解凍する [#i11a99aa] -指定したzipファイルをtmpフォルダ以下に解凍するサンプル #pre{{ Zip::File.open('data/demo.zip') do |zipfile| zipfile.each do |entry| puts "extracting #{entry.name}" entry.extract('tmp/' + entry.name) end end }} *トラブルシューティング [#ed06a0ca] **ファイルに出力すると^Mが表示される。 [#a3f30012] -[[^M (ハットM)記号について - Fakin'it:http://fakinit.xrea.jp/fakinit/2009/07/m-m.html]]に書いてあるように、^MはCR(=\r)に相当することを前提として、例えば次ぎのようなプログラムをWindows環境で動かす。 #pre{{ f = File.open("log.txt", "w") f.print("abc\r\n") f.close }} -するとlog.txtには次のような文字が書き出される(しかもエディタで見るとcrlfモード)。 abc^M -これはファイルをテキストモードで書き出しオープン(="w")しているため。\nが\r\nに変換されて書き出されるため、結局ファイルには"abc\r\r\n"が書き出されていることになる。末尾の\r\nがcrlfモードとしてエディタに認識され、残った\rが^Mとして画面に表示されることになる。