Rubyでパス名をオブジェクトっぽく使う【Pathname】
- 環境
- Windows10
- Ruby 2.7.2
- 参考
- class Pathname (Ruby 3.0.0 リファレンスマニュアル) <https://docs.ruby-lang.org/ja/latest/class/Pathname.html >
大体下記の進化版
Pathnameオブジェクトを作る
引数にパス文字列を渡すだけ。ワイルドカードでも可能
パスの存在有無は問わない
require 'pathname'
home_pass_str = "C:/Users/xxx"
home_pass = Pathname.new(home_pass_str)
#home_pass = Pathname(home_pass_str) # こっちでも可
puts home_pass.to_s # => C:/Users/xxx
ただし、区切り文字は/
(スラッシュ)にする、文字コードをUTF-8にする必要がある
パスを連結する
おそらく一番便利なやつ。
普通の文字列で複数連結しようとすると長くなってしまうが、Pathnameなら/
で自然に?繋げられる
home_pass_str = "C:/Users/xxx"
#home_pass_str = "C:/Users/xxx/" # 最後に/がついていても結果は同じ
home_pass = Pathname.new(home_pass_str)
input_pass = home_pass / "yyy" / "zzz" # 連結
puts input_pass.to_s # => C:/Users/xxx/yyy/zzz
指定パスが存在するかチェック
真偽を返す。パスがワイルドカード指定だとうまく行かない
メソッド | trueを返す条件 |
---|---|
pass.exist? |
passが存在する |
pass.directory? |
passがディレクトリ |
pass.file? |
passがファイル |
home_pass = Pathname.new("C:/Users/xxx")
# !FileTest.exist?(home_pass.to_s)と同等
if !home_pass.exist?
raise ArgumentError, "パス #{home_pass} は存在しません"
end
パスがワイルドカード指定の場合
file_pass_str = "C:/Users/xxx/test*.txt"
# Dir.glob(file_pass_str).empty? と同等
if Pathname.glob(file_pass_str).empty?
raise ArgumentError, "パス #{file_pass_str} が正しくありません"
end
ディレクトリ配下のファイルをすべて検索
※パスが存在しない場合はループに入らない(エラーも出ない)
home_pass = Pathname.new("C:/Users/xxx")
# Dir.glob("#{home_pass.to_s}/**/*") と同等
Pathname.glob(home_pass / "**/*") do |pass|
next if pass.directory? # ディレクトリは無視
puts pass
end
直下のファイルだけを取得
再帰的には検索しない
home_pass = Pathname.new("C:/Users/xxx")
home_pass.each_child do |pass|
next if pass.directory? # ディレクトリは無視
puts pass
end
# パスが存在しないときは Errno::EXXX: エラーが発生
ファイル名・ディレクトリ名を取得
File.basename
と同じ
pass = Pathname.new("C:/Users/xxx/test.txt")
file_name = pass.basename
# => test.txt
pass = Pathname.new("C:/Users/xxx")
file_name = pass.basename
# => xxx
ファイルを読み込む
※パスがワイルドカードのときはエラー(順番に読み込んではくれない)
まとめて読み込む
# test.txt は UTF-8 で書かれている
test_pass = Pathname.new("test.txt")
test_pass.open(mode = "r", :external_encoding => "UTF-8") do |file|
puts file.read # 全部出力
end
1行ずつ
# test.txt は UTF-8 で書かれている
test_pass = Pathname.new("test.txt")
test_pass.each_line(:external_encoding => "UTF-8") do |line|
line.chomp! # 改行削除
next if (line == "") # 空行を無視
puts line
end