88

Is there a single way of detecting if a directory/file/symlink/etc. entity (more generalized) exists?

I need a single function because I need to check an array of paths that could be directories, files or symlinks. I know File.exists?"file_path" works for directories and files but not for symlinks (which is File.symlink?"symlink_path").

codeforester
  • 39,467
  • 16
  • 112
  • 140
claudiut
  • 1,643
  • 4
  • 15
  • 20
  • 1
    What version of Ruby are you using? File.exists? works for symlinks for me in Ruby 1.9.2 in OS X 10.6.6 –  Feb 04 '11 at 15:45
  • 1
    To clarify: for symlinks, you're asking for something that returns `true` if the symlink exists, regardless of whether it can be ultimately resolved to a non-symlink. I.e. it should return `true` for broken links as well. `File.exists?` will only return `true` for a symlink that's not broken. – Kelvin May 19 '16 at 18:04

3 Answers3

155

The standard File module has the usual file tests available:

RUBY_VERSION # => "1.9.2"
bashrc = ENV['HOME'] + '/.bashrc'
File.exist?(bashrc) # => true
File.file?(bashrc)  # => true
File.directory?(bashrc) # => false

You should be able to find what you want there.


OP: "Thanks but I need all three true or false"

Obviously not. Ok, try something like:

def file_dir_or_symlink_exists?(path_to_file)
  File.exist?(path_to_file) || File.symlink?(path_to_file)
end

file_dir_or_symlink_exists?(bashrc)                            # => true
file_dir_or_symlink_exists?('/Users')                          # => true
file_dir_or_symlink_exists?('/usr/bin/ruby')                   # => true
file_dir_or_symlink_exists?('some/bogus/path/to/a/black/hole') # => false
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • 1
    I would advise against doing raw string concatenation (`ENV['HOME'] + '/.bashrc'`) which may not work cross-platform. You should use Ruby File joins and also why not start from `Rails.root` if you are using Rails. `File.exists?(Rails.root.join('db', 'my_seeds.csv')` – Cyril Duchon-Doris Dec 15 '16 at 16:35
  • 2
    It's guaranteed to not work cross-platform since Windows doesn't know about Bash, and hence, about .bashrc. But it'd work on a *nix-based platform. The use of `/` isn't the issue though, since [Ruby's IO automatically converts from forward slashes to back slashes on Windows](http://ruby-doc.org/core-2.3.3/IO.html). – the Tin Man Dec 15 '16 at 17:26
  • Maybe that was true in December 2016, but Windows definitely _does_ know about Bash these days. :-) I can type `bash` into the Start Menu, and in the resulting console window, `cat ~/.bashrc` produces output. ¯\\_(ツ)_/¯ – Jonathan Gilbert Jul 24 '18 at 15:31
  • The answer by Cyril is unfortunately not fully correct - string concatenation DOES work on windows do for "File.exist?" checks, as the Tin Man already pointed out. I only added this comment here to confirm it. – shevy Oct 12 '18 at 12:39
15

Why not define your own function File.exists?(path) or File.symlink?(path) and use that?

Gintautas Miliauskas
  • 7,744
  • 4
  • 32
  • 34
  • Of course I can do that, but I would like a way already implemented that can check both of them. I mean to check if at that path there is 'something'. – claudiut Feb 04 '11 at 12:02
  • 2
    @Clawsy I think you're missing Gintautas's point: you're a programmer - if the function you need doesn't exist, you can create it. – Telemachus Feb 04 '11 at 12:29
  • 2
    No, I am not missing the point :). I understand perfectly. I just want to add as little code as possible to my application. In my case, it is better (for software engineering matters) if I find a method like that. If not, that is... I make one, no problem. I just wanted to know if there is a predefined one. I am not lazy, it's just inserting a code in a HUGE application that must be very well taken care of. I just wanted to know that.... because I don't want to repeat myself. (DRY - Do Not Repeat Yourself, from Pragmatic Programmer book :D). – claudiut Feb 04 '11 at 13:20
  • 4
    Why reinvent the wheel when it's already part of the language? – the Tin Man Feb 04 '11 at 14:04
  • 11
    I find it very useful not to obsess about detail too much in programming. If you know a straightforward and simple way to solve a problem, just do it. If you find a better way some time later, you can always go back and fix. Defining a new function is a no-brainer in this situation. – Gintautas Miliauskas Feb 07 '11 at 13:26
  • 5
    But, the functionality is already built into the language and is simple to use. It then becomes a case of reading to see what is available and adding the call. Writing code to implement functionality that already exists just because you didn't take the time to read an RDoc that comes with the language... just doesn't add up to me. By that logic you could end up rewriting the standard library. – the Tin Man Feb 07 '11 at 22:57
  • This method must exist in the core somewhere! I shall continue to search for it until it magically appears, or until the end of days, whichever comes first. It's worth it to save one extra method call. – Jerome Nov 30 '13 at 21:27
  • 2
    Use File.exist? instead of File.exists? as this is deprecated in ruby 2.2.0: http://ruby-doc.org/core-2.2.0/File.html#method-c-exists-3F – atw Jun 16 '16 at 09:09
0

Just File.exist? on it's own will take care of all of the above for you

grepsedawk
  • 3,324
  • 2
  • 26
  • 49