TIL: Pathname for file operations

I used Ruby extensively at Twitter and it remains one of my favorite languages, especially for tools and scripts. That said, my knowledge of production Ruby is largely from the 1.8.7 / 1.9.3 era, which is quite old. We’re now on Ruby 4.0.

I still write a lot of scripts and these days I ask Claude to write many of them for me. I noticed it wrote some stuff using the Pathname module. I assumed it was a newer addition to the language, but it’s extremely old–it was created in 2003.

Pathname wraps a path and provides an OO facade for lots of common file operations from different modules like File, Dir, and FileUtils. Without Pathname, you pass the path around and call methods:

dir = "./config"
path = File.join(dir, "app.json")

File.exist?(path)
File.read(path)
File.write(path, "new content")
File.directory?(path)
f = File.open(path)

With Pathname, you wrap the path and then can call methods on it directly:

dir = Pathname.new("./config")
path = dir + "app.json"

path.exist?
path.read
path.write("new content")
path.directory?
f = path.open

The facade for methods that typically return string paths wraps them as Pathname so it’s easy to chain:

dir = "./config"
Dir.glob(File.join(dir, "*.json")).each {|p| File.read(p) }

dir = Pathname.new("./config")
dir.glob("*.json").each {|p| p.read }

I wish I had known about Pathname sooner because I definitely would have used it more. Especially in Ruby, which emphasizes everything-is-an-object, it’s a nice improvement to my previous handling of paths.