Something that stinks about Ruby’s core library
22 Apr 2010
Something that stinks about Ruby’s core library
The other day my teammate said, “I finally found something that stinks about Ruby’s core library.”
What was wrinkling his nose? The Dir class gives you no way to ask for files only, or for directories only. He had a point. The Dir.entries is inflexible. And even the flexible …
I really disagree with Nils Jonsson’s take on ruby’s standard library and so does matz. Nils claims that Something stinks about Ruby’s Core Library, and goes on to provide an implementation for Dir.files and Dir.directories. Yes, there might be functionality that is missing here, but it’s trival to implement. His solution shells which is both dangerous and non-portable. It’s also unnecessarily complex. The beauty of ruby is that it can be changed in very simple ways to solve your problem - even the core library. Here’s my alternative (and much shorter and portable) solution:
class Dir
def self.directories(path)
Dir.new(path).entries.select do |e|
File.directory?(File.join(path, e))
end
end
def self.files(path)
Dir.new(path).entries.select do |e|
File.file?(File.join(path,e))
end
end
end
Now, his two main arguments were:
- if you don’t mind some computing time and space wasted and you want to write as little code as possible
- if you know the contents of the directory in advance
The computing time and space will be much much worse with forking out to the shell listing all of the files, then gsubing out the items with a trailing slash. The ruby filtering will be much faster. But, if performance is a concern, I’m sure my code could be re-written as ruby C much like the rest of the Dir class, and it would be even faster. In the non-windows example, ‘ls -d’ is begin used to filter. In most POSIX implementations of ls, it uses opendir(), readir(), and stat(). So, ls is looking at each file and determining if it is a directory or not. This could potentially be sped up by using scandir(), but that’s a newer POSIX standard, so it might not be available on older unix systems.
nerd ruby