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