`File::exist?`和`File::exists?`的区别

16
ruby-doc中,File::exist?File::exists? 的文档条目是重复的,但它们使用不同的语义:一个条目表示如果 file_name 是一个目录,则返回true; 另一个条目表示如果 file_name 是一个文件,则返回true
我认为这两个条目都不正确。这两个方法似乎都是在 file.c 中使用 rb_file_exist_p 实现的,它似乎会尝试调用fstat()(如果传递的值是 IO)或stat()(如果它是字符串)。 fstat()stat() 在成功时返回0,错误时返回-1,并将此传递回 rb_file_exist_p,然后转换为布尔结果。 我觉得:
  1. 有两种使代码更易读的方法;没有语义上的区别。
  2. 两者都不关心文件是否存在,而是关心类似于文件的对象是否存在,例如文件、目录、套接字、FIFO 等。
  3. 也许文档可以说明这些方法告诉调用者是否存在具有类似文件的语义的对象,但更具体的测试将表明它实际上是什么类型:例如目录(directory?),文件(file?),套接字(socket?)等。
我的理解(缺乏)这些方法之间的差异是否正确,并且是否值得建议更改文档?

这个问题应该在 Ruby-talk 上提问,那里会有所帮助。或者你可以在 git 上查看源代码,进行更改并提出拉取请求。就我个人而言,我认为这不是一个大问题,因为“-e”(“存在”)是 *nix 系统上的一个标志,它可以平等地处理文件和目录。对于文件和目录有单独的条目这一点对我来说只是小问题。总的来说,我认为这个问题不适合在 SO 上讨论,并且似乎属于“不具建设性”的范畴。 - the Tin Man
4
@theTinMan:我不太同意,我认为澄清混乱和错误的文档是一个实际的编程问题,至少可以归类为“编程职业中独特的实际可回答问题”。 - mu is too short
4个回答

26
请参见其他答案获取更高版本Ruby的信息。据我所知,2.2中已将exists?标记为弃用。

如果我们查看C源代码,我们会看到这样的内容

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);

所以File.exist?File.exists?是完全相同的东西,相应的文档如下:

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

rb_file_exist_p C函数只是rb_stat的一个非常薄的包装器,它是STAT宏的包装器,STAT只是stat系统调用的可移植性包装器。因此,上面的文档是正确的:如果文件存在,则File#exist?返回true

如果我们检查file.c中关于目录的文档片段,我们可以找到这个

/*
 * 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.
 *
 */

看起来文档生成器混淆了Dir.exist?File.exist?的文档,因为它们被记录在file.c中,尽管Dir是在dir.c中定义的
潜在的问题似乎是源代码的排列顺序与文档生成器的预期不符,导致文档混乱和错误。但我不确定应该如何解决这个问题。

好的,我没有考虑到生成器 - 我会看看如何提交补丁给那个/那些 - 谢谢 - Leif
我认为显而易见的解决方法要么是1)告诉RDoc开发人员他们的前提是无效的,要么是2)建议Ruby开发人员将Dir.exist?Dir.exists?文档移动到dir.c - sawa
1
对代码进行了深入的调查以发现答案。不幸的是,这个答案现在已经过时了,因为这些方法不再相同。File.exists?已被弃用,请参阅其他答案获取更多信息。 - Clint Pachl
@muistooshort,您能否请添加您回答适用的Ruby版本号吗? - Ben Sandeen
据我所知,exists?在2.2中已被弃用,如下所示Daniel Romero - mu is too short
显示剩余2条评论

12

10

File.exist?File.exists?现在已经不完全相同了。请查看https://github.com/ruby/ruby/blob/ruby_2_3/file.c#L5920

define_filetest_function("exist?", rb_file_exist_p, 1);
define_filetest_function("exists?", rb_file_exists_p, 1);

rb_file_exists_p 包含以下代码行:

rb_warning("%sexists? is a deprecated name, use %sexist? instead", s, s);

所以你应该坚持使用File.exist?


2

git pull 使其消失 - 这个问题已经在这里得到解决,但不确定为什么 Ruby-doc 和 apidock 上的文档仍然错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接