What is the difference between Ruby's Dir, File, and Pathname classes? They seem to share common methods like basename
, dirname
, glob
, and join
. When is using one advantageous over the other?
Pathname seems particularly peculiar when comparing its functionality to Dir and File.
Objects of class Dir are directory streams representing directories in the underlying file system. They provide a variety of ways to list directories and their contents.
The pathname is a specific label for a file's directory location while within an operating system. In traditional DOS command line systems, the user would type the entire file pathname into the system to be directed to that file where it is located inside of the operating system.
__FILE__ is the filename with extension of the file containing the code being executed. In foo. rb , __FILE__ would be "foo. rb".
According to the Ruby docs for Dir, File, and Pathname, they definitely appear to have a lot in common.
The principle different between Dir
and File
seems to be that Dir
assumes the object it's working with is a directory and File
assumes files. For most purposes they can apparently be used interchangeably, but even if the code works, it might be confusing to anyone reading your code if you manipulate directories using File
and files using Dir
.
Pathname
looks to be a multi-OS method of locating files and directories. Since Windows and *nix machines handle file management differently it can be a pain to refer to files or directories in an OS-specific way if you want scripts to run anywhere. From the docs:
Pathname represents a pathname which locates a file in a filesystem. The pathname depends on OS: Unix, Windows, etc. Pathname library works with pathnames of local OS. However non-Unix pathnames are supported experimentally.
It does not represent the file itself. A Pathname can be relative or absolute. It’s not until you try to reference the file that it even matters whether the file exists or not.
Pathname is immutable. It has no method for destructive update.
Hope this helps.
Pathname is particularly interesting because it comes with the convinience of manipulating paths and avoiding the back and forth string manipulation when using that string in File and Dir class names. An example:
require 'pathname'
def log_stuff(directory, data)
path = Pathname.new(directory)
raise "Directory does not exist" unless path.exist?
raise "Path given is not a directory" unless path.directory?
path += "development.log"
path.open("a") { |io| io.write data }
end
You can also see it is being used in Rails' path which also enables you to do some cool stuff:
$ rails c
> Rails.root
=> #<Pathname:/home/kibet/code/ruby/sample_app>
> Rails.root.join("config", "database.yml")
=> #<Pathname:/home/kibet/code/ruby/sample_app/config/database.yml>
> _.read
=> "development:\n adapter: postgresql\n...
as opposed to File.join(Rails.root, "config", "database.yml")
.
One of the best resources can be the language docs which, in this case, is http://www.ruby-doc.org/
Dir is working with directories, and examples include listing the current working directory (pwd
), making directories and deleting them.
File is similar to Dir but instead deals with working with Files, such has getting and changing permissions, creating files and deleting them.
Pathname is peculiar, as you say, because it does include all the functionality of File and some of that of Dir, but if you read the docs it tells you exactly why it is there. From http://www.ruby-doc.org/stdlib-1.9.3/libdoc/pathname/rdoc/Pathname.html:
The value of this class is to manipulate file path information in a neater way than standard Ruby provides. The examples below demonstrate the difference. All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
Hope that helps explain things.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With