在ruby中从一个目录中获取所有文件的最好方法是什么?


当前回答

最好的方法是将目录添加到加载路径,然后要求每个文件的基名。这是因为您希望避免意外地两次需要相同的文件——这通常不是预期的行为。一个文件是否会被加载取决于require之前是否看到过传递给它的路径。例如,这个简单的irb会话表明,您可能会错误地要求并加载同一个文件两次。

$ irb
irb(main):001:0> require 'test'
=> true
irb(main):002:0> require './test'
=> true
irb(main):003:0> require './test.rb'
=> false
irb(main):004:0> require 'test'
=> false

请注意,前两行返回true,这意味着两次都加载了相同的文件。当使用路径时,即使路径指向相同的位置,require也不知道该文件已经被需要了。

在这里,我们将一个目录添加到加载路径中,然后要求每个*的基名。Rb文件。

dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }

如果您不关心文件是否被多次要求,或者您的目的只是加载文件的内容,那么也许应该使用load而不是require。在本例中使用load,因为它能更好地表达您要完成的任务。例如:

Dir["/path/to/directory/*.rb"].each {|file| load file }

其他回答

而不是像在一些答案连接路径,我使用File.expand_path:

Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
  require file
end

更新:

而不是使用文件。Dirname你可以这样做:

Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
  require file
end

在哪里. .删除__FILE__的文件名。

如何:

Dir["/path/to/directory/*.rb"].each {|file| require file }
Dir[File.join(__dir__, "/app/**/*.rb")].each do |file|
  require file
end

这将在您的本地机器和不使用相对路径的远程(如Heroku)上递归地工作。

如果它是一个相对于执行要求的文件的目录(例如,你想加载lib目录中的所有文件):

Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }

编辑:根据下面的评论,更新版本:

Dir[File.join(__dir__, 'lib', '*.rb')].each { |file| require file }

在Rails中,你可以做:

Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }

更新:修正了@Jiggneshh Gohel删除斜杠的建议。