Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between `File::exist?` and `File::exists?`

Tags:

ruby

On ruby-doc, the documentation entries for File::exist? and File::exists? are duplicated with different semantics: one entry says returns true if file_name is a directory; the other says returns true if file_name is a file.

I don't think either entry is correct. Both methods seem to be implemented in file.c using rb_file_exist_p, which, seems to try to call fstat() if the value passed is an IO, or stat() if it's a string. Both fstat() and stat() return 0 on success and -1 on error, and this is passed back to rb_file_exist_p, and turned into a boolean result. It seems to me that

  1. there are two methods for making code read more easily; there are no semantic differences
  2. neither really relates to a file existing, but to whether a file-like item exists, e.g. a file, a dir, a socket, a fifo etc.
  3. perhaps the document could say that the methods tell the caller whether or not a thing that has file-like semantics is there, but more specific tests will tell what it actually is: e.g. directory?, file?, socket? etc.

Is my understanding of the (lack of) difference in the methods correct, and is it worth suggesting a change to the document ?

like image 723
Leif Avatar asked Jan 13 '13 05:01

Leif


1 Answers

Note that the answer to this question depends on the Ruby version. See the other answers for newer versions of Ruby. AFAIK exists? was deprecated in 2.2.


If we look at the C source, we see this:

rb_cFile = rb_define_class("File", rb_cIO);
/* ... */
define_filetest_function("exist?", rb_file_exist_p, 1);
define_filetest_function("exists?", rb_file_exist_p, 1);

So File.exist? and File.exists? are exactly the same thing and the corresponding documentation is:

Return <code>true</code> if the named file exists.

The rb_file_exist_p C function is just a very thin wrapper around rb_stat, that's a wrapper for the STAT macro, and STAT is just a portability wrapper for the stat system call. So, the documentation above is correct: File#exist? returns true if the file exists.

If we check file.c for the documentation snippet that talks about directories, we find this:

/*
 * Document-method: exist?
 *
 * call-seq:
 *   Dir.exist?(file_name)   ->  true or false
 *   Dir.exists?(file_name)   ->  true or false
 *
 * Returns <code>true</code> if the named file is a directory,
 * <code>false</code> otherwise.
 *
 */

So it looks like the documentation generator is getting confused because Dir.exist? and File.exist? are documented in file.c even though Dir is defined in dir.c.

The underlying problem seems to be that the source code arrangement doesn't match what the documentation generator expects and the result is confused and incorrect documentation. I'm not sure how this should be fixed though.

like image 79
mu is too short Avatar answered Sep 23 '22 07:09

mu is too short