使用Ruby获取文件夹中所有文件的名称

432

我想使用Ruby从一个文件夹中获取所有文件名。

19个回答

629

你还可以选择快捷方式

Dir["/path/to/search/*"]

如果您想在任何文件夹或子文件夹中查找所有的Ruby文件:

Dir["/path/to/search/**/*.rb"]

6
您可以使用Dir::glob()来进行相同的操作。 - Yoann Le Touche
2
此外,请使用 ./... 而不是 ~/ - Minh Triet
5
为什么这个被优先选择? - BvuRVKyUVlViVIc7
1
@MinhTriet 那是做什么的?它更可取吗? - stephenmurdoch
9
@marflar - ./ 表示当前目录,而 / 是根挂载点,~/ 是用户的主目录。如果您将整个项目移动到其他位置,第一个表示法仍然有效,但其他两个可能会失效。 - mirichan
请注意,Dir ["/path/to/search/**/."] 还会返回名称中带有“.”的文件夹/子文件夹。您需要使用 File.file?(file_or_folder_name)进行额外检查以捕获它们。 - dwkns

207

18
看起来他正在使用 Stack Overflow 来记录他刚刚提出的问题的答案。我想这是一种备忘录吧。我认为这没有什么问题——毕竟,即使这个答案有点不完整(例如可能应该提到 Dir#glob),也没有阻止其他人发布一个真正好的答案。当然,我更多地是一个“看到积极方面”的人…… - Mike Woodhouse
1
@Mike:从大局来看,这可能并不是什么大事。正如你所说,如果问题和答案都很好,那么总体上来说,这可能是一个优点。但是在这里,问题和答案都非常简单,似乎并没有特别有用。 - Telemachus
25
@Telemachus,我很少使用Dir,每次需要使用它时都需要阅读文档。我在这里发布了我的问题和答案,以便以后能够找到它,并可能帮助有同样问题的人。我认为我听过 SO 播客中说过这种行为没有问题。如果您有更好的答案,请发布。我已经发表了我所知道的内容,我不是 Ruby 忍者。我定期接受得票最多的答案。 - Željko Filipin
当参数是一个变量时,这可能比Dir[]Dir.glob更好。当path = '/tmp'时,比较:Dir.glob("#{path}/*")Dir.entries(path)。返回值略有不同(“。”,“..”),但后者在快速浏览时更容易理解。 - Benjamin Oakes
1
Dir.entries会返回一个包含“.”和“..”的列表。如果你不想要它们,可以使用Dir.each_child。 - user1142217
显示剩余3条评论

101
以下片段准确地显示了目录中文件的名称,跳过子目录和"."".."点文件夹:
Dir.entries("your/folder").select { |f| File.file? File.join("your/folder", f) }

21
也可以使用 ...select {|f| File.file? f},这样语法更短且意思更明确。 - Automatico
2
我发现Dir.entries没有在返回文件名时给出完整路径,所以这个解决方案对我不起作用。 - James McMahon
2
@squixy 你写对了吗?:Dir.entries("your/folder").select {|f| File.file? f} - Automatico
10
是的,!File.directory? 可以工作,但 File.file? 不行。 - Kamil Lelonek
6
.reject {|f| File.directory? f} 看起来比 .select{|f| !File.directory? f} 更简洁。哦,现在我看到了第一个评论...也不错。 - Ian
显示剩余4条评论

51

27

27
这对我很有效:
如果你不想要隐藏文件[1],请使用 Dir[]
# With a relative path, Dir[] will return relative paths 
# as `[ './myfile', ... ]`
#
Dir[ './*' ].select{ |f| File.file? f } 

# Want just the filename?
# as: [ 'myfile', ... ]
#
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.basename f }

# Turn them into absolute paths?
# [ '/path/to/myfile', ... ]
#
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.absolute_path f }

# With an absolute path, Dir[] will return absolute paths:
# as: [ '/home/../home/test/myfile', ... ]
#
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }

# Need the paths to be canonical?
# as: [ '/home/test/myfile', ... ]
#
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }.map{ |f| File.expand_path f }

现在,Dir.entries将返回隐藏文件,并且您不需要通配符星号(您只需传递带有目录名称的变量),但它将直接返回基本名称,因此File.xxx函数将无法工作。
# In the current working dir:
#
Dir.entries( '.' ).select{ |f| File.file? f }

# In another directory, relative or otherwise, you need to transform the path 
# so it is either absolute, or relative to the current working dir to call File.xxx functions:
#
home = "/home/test"
Dir.entries( home ).select{ |f| File.file? File.join( home, f ) }

[1] 在Unix上,.dotfile,我不了解Windows的情况。


11

此代码仅返回带有其扩展名的文件名(不包括全局路径)

Dir.children("/path/to/search/")

=> [文件1.rb、文件2.html、文件3.js]


这里有一个很好的解释:https://www.bigbinary.com/blog/ruby-2_5-introduces-dir-children-and-dir-each_child - fguillen

10

就我个人而言,我发现这对于在文件夹中循环遍历文件、前向安全非常有用:

Dir['/etc/path/*'].each do |file_name|
  next if File.directory? file_name 
end

10

这是一个寻找目录中文件的解决方案:

files = Dir["/work/myfolder/**/*.txt"]

files.each do |file_name|
  if !File.directory? file_name
    puts file_name
    File.open(file_name) do |file|
      file.each_line do |line|
        if line =~ /banco1/
          puts "Found: #{line}"
        end
      end
    end
  end
end

6
在获取目录中所有文件名时,可以使用此片段来拒绝两个目录[...]和以.开头的隐藏文件。
files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}

Dir.entries 返回的是本地文件名,而不是绝对文件路径。另一方面,File.directory? 期望一个绝对文件路径。这段代码无法按预期工作。 - Nathan
很奇怪,代码在你的情况下不起作用。因为这是我在一个正常运行的应用程序中使用过的代码。我会重新检查我的代码,如果原来的工作代码有任何遗漏,我会在这里发布 :) - Lahiru Jayaratne
1
@Nathan 请查看我的答案以获取解释。 - user1115652
1
这个答案是一个重复的答案,与2013年添加的答案相同。 - Hirurg103

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