ifelse mark thomas

How To Check If A File or Directory Exists in Ruby

In this post we look at a few ways you can check to ensure that a file or directory exists using Ruby.

Even though JavaScript (and node.js!) is/are my first programming language love(s)[^n], I've been trying to hone my skills in Ruby and Python to better merit the whole 'full-stack' title thing. Also because there are some really great things that python and ruby are great for that JavaScript isn't (vice-versa for each language, really).

So, I'll occasionally be sharing some small tips/tricks I pick up along the way in these other realms. One I found helpful was how to effectively check for a file's existence and some of the gotchas that come along with the solutions.

Esiste?

If you've ever worked with IO (especially reading/writing files), you'll probably agree that it tends to be a good idea to ensure a file, path, directory, or whatever else exists before trying to use it in your software. The following are a few ways you can check to ensure that a file or directory exists using Ruby.

File.exist?()

File.exist?(<filename || IO object>), -> true or false

This method essentially answers whether the stat() or fstat() system calls are successful. So, you have to be careful in what assumptions you make about this method — it will return true for directories.

File.exists?()

Deprecated! Don't forget to toss out that extra s!

File.file?()

File.file?(<file || IO object>), -> true or false

Returns true if the named file exists and is a regular file. file can be an IO object. If the file argument is a symbolic link, it will resolve the symbolic link and use the file referenced by the link.

File.file?('~/myDir')
# `file?` will only return `true` for files, not directories
=> false
File.file?('myFile.png')
=> true

File.directory?()

directory?(file_name), -> true or false

Returns true if the named file is a directory, or a symlink that points at a directory, and false otherwise. As usual, file_name can be an IO object.

So, if you want to check for a file, you should probably use File.file?(). Otherwise, you'll probably want to stick with File.directory?().

[^n]: Our relationship is very solid now, but initially everything was very confusing due to some ducktyping and some prototypal and/or delegative misunderstanding