在Ruby中,__FILE__的含义是什么?

229

我经常在Ruby中看到这种情况:

require File.dirname(__FILE__) + "/../../config/environment"  

__FILE__ 是什么意思?


为了帮助联系引用,还请参阅 https://www.ruby-forum.com/topic/143383 和 https://dev59.com/UG855IYBdhLWcg3weEKJ?lq=1。 - the Tin Man
4个回答

156

这是对当前文件名的引用。在文件foo.rb中,__FILE__将被解释为"foo.rb"

编辑: Ruby 1.9.2和1.9.3的行为似乎与Luke Bayes在他的评论中所说的有些不同。使用以下文件:

# test.rb
puts __FILE__
require './dir2/test.rb'
# dir2/test.rb
puts __FILE__

运行ruby test.rb将输出

test.rb
/full/path/to/dir2/test.rb

91
这个答案不准确。__FILE__是相对于当前执行目录的“相对”路径,而不是绝对路径。您必须使用File.expand_path(FILE)来获取绝对路径。 - Luke Bayes
8
上面的注释中双下划线已被自动移除。 - Luke Bayes
5
在1.9.2版本中,它的工作方式有些不同。最初加载的文件具有相对路径的 __FILE__,但其他被包含或需要的文件具有绝对路径。 - Geoff
11
您可以使用反引号将字面文本括起来,以保留在Stack Overflow评论中下划线和其他特殊字符。写上\__FILE__`可得到__FILE__`。 - Rory O'Kane
1
@RoryO'Kane 在有人误读并尝试在 Ruby 脚本中输入 \__FILE__`` 之前,请不要在 Ruby 中编写此代码,除非你想让世界可能爆炸。 - Ben Aubin
显示剩余3条评论

64

__FILE__的值是相对路径,在文件被加载时创建并存储(但从不更新)。这意味着,如果您在应用程序的其他地方调用了Dir.chdir,则该路径将被错误地展开。

puts __FILE__
Dir.chdir '../../'
puts __FILE__

解决这个问题的一个方法是将__FILE__的扩展值存储在任何应用程序代码之外。只要你的require语句位于定义的顶部(或者至少在任何对Dir.chdir的调用之前),这个值在更改目录后仍然会有用。

$MY_FILE_PATH = File.expand_path(File.dirname(__FILE__))

# open class and do some stuff that changes directory

puts $MY_FILE_PATH

1
这意味着,如果您的应用程序中有任何对Dir.chdir的调用,该路径将不正确地扩展。在我的测试中,路径已正确扩展。我的Ruby版本是2.3.7,也许更新的Ruby版本已经解决了这个问题。 - Alec.Zhou

29

__FILE__ 是包含执行代码的文件的带扩展名的文件名。

foo.rb 中,__FILE__ 将是 "foo.rb"。

如果 foo.rb 在目录 /home/josh 中,则 File.dirname(__FILE__) 将返回 /home/josh


确实很需要这个。+1 :=) @Ethan - K M Rakibul Islam
1
这里提供文档链接 here - Ross Attrill

18
在Ruby中(至少在Windows版本中),我刚刚检查了一下,__FILE__不包含文件的完整路径。它包含相对于执行文件的路径。

而在PHP中,__FILE__是完整路径(我认为这更好)。这就是为什么为了使你的路径在Ruby中可移植,你真的需要使用这个的原因:
File.expand_path(File.dirname(__FILE__) + "relative/path/to/file")

需要注意的是,在Ruby 1.9.1中,__FILE__包含文件的完整路径。上述描述是针对我使用Ruby 1.8.7时的情况。

为了兼容Ruby 1.8.7和1.9.1(不确定1.9),您应该使用我上面展示的结构来引入文件。


1
你需要在你的相对路径前面添加一个斜杠: File.expand_path(File.dirname(__FILE__) + "/relative/path/to/file") - Felix Rabe
4
永远不要硬编码目录分隔符,而应该使用File.join代替:File.expand_path(File.join(File.dirname(__FILE__), "relative", "path", "to", "file")) - Andrew Hodgkinson
Andrew,请帮我一下好吗?我正在使用以下代码将内容写入文件:path = YAML::load_file(File.open(File.join(File.dirname(FILE) + "/massa/users.yml"))) path[:cad_user][:user] = input_email_create.value File.open(File.join(File.dirname(FILE) + '/massa/users.yml'), 'w') {|f| f.write path.to_yaml }但是我收到了这个错误信息:No such file or directory @ rb_sysopen。 - Tadeu
不确定它在过去的行为如何,但现在对于第一个(主)文件,__FILE__ == $0,而对于其余文件则是绝对路径。这对于__FILE__ == $0类型的检查(自执行文件)非常方便。更多信息请参见我的其他评论 - x-yuri

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