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

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

303662 次浏览
Dir.entries(folder)

例子:

Dir.entries(".")

来源:http://ruby-doc.org/core/classes/Dir.html#method-c-entries

您还有快捷方式选项

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

如果你想在任何文件夹或子文件夹中找到所有Ruby文件:

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

下面的代码片段精确地显示了目录内的文件名称,跳过子目录和"."".."虚线文件夹:

Dir.entries("your/folder").select { |f| File.file? File.join("your/folder", f) }

要递归地获取所有文件(严格来说只针对文件):

Dir.glob('path/**/*').select { |e| File.file? e }

或者任何不是目录的文件(File.file?将拒绝非常规文件):

Dir.glob('path/**/*').reject { |e| File.directory? e }

可选择的解决方案

使用Find#find而不是像Dir.glob这样基于模式的查找方法实际上更好。看到这是对“在Ruby中递归地列出目录的一行程序?”

就我个人而言,我发现这对于在文件夹中循环文件最有用,前瞻性安全:

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

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

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

在获取目录中的所有文件名时,此代码段可用于拒绝目录[...]和以.开头的隐藏文件

files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}
def get_path_content(dir)
queue = Queue.new
result = []
queue << dir
until queue.empty?
current = queue.pop
Dir.entries(current).each { |file|
full_name = File.join(current, file)
if not (File.directory? full_name)
result << full_name
elsif file != '.' and file != '..'
queue << full_name
end
}
end
result
end

返回文件在目录和所有子目录中的相对路径

这对我来说很管用:

如果你不想要隐藏文件[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将返回隐藏文件,并且您不需要通配符asterix(您可以将目录名传递给变量),但它将直接返回basename,因此File. xml文件将返回。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] .dotfile在unix上,我不知道Windows

如果你想获得文件名数组包括符号链接,使用

Dir.new('/path/to/dir').entries.reject { |f| File.directory? f }

甚至

Dir.new('/path/to/dir').reject { |f| File.directory? f }

如果你想去没有符号链接,使用

Dir.new('/path/to/dir').select { |f| File.file? f }

如其他答案所示,如果你想递归地获得所有文件,使用Dir.glob('/path/to/dir/**/*')而不是Dir.new('/path/to/dir')

Dir.new('/home/user/foldername').each { |file| puts file }

这是对我有效的方法:

Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }

Dir.entries返回一个字符串数组。然后,我们必须为File.file?提供文件的完整路径,除非dir等于我们当前的工作目录。这就是为什么File.join()

你可能还想使用Rake::FileList(前提是你有rake依赖):

FileList.new('lib/*') do |file|
p file
end

根据API:

文件列表是懒惰的。当给出可能的glob模式列表时 要包含在文件列表中的文件,而不是搜索文件 结构来查找文件,FileList保存后者的模式 使用。< / p >

https://docs.ruby-lang.org/en/2.1.0/Rake/FileList.html

在Ruby 2.5中,你现在可以使用Dir.children。它以数组的形式获取文件名,除了"."和".."

例子:

Dir.children("testdir")   #=> ["config.h", "main.rb"]

http://ruby-doc.org/core-2.5.0/Dir.html#method-c-children

除了在这个线程中的建议,我想提到的是,如果你需要返回点文件以及(。gitignore等),与Dir。Glob你需要包括一个标志,如下所示: Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH) 默认为Dir。条目包括点文件,以及当前的父目录

对于感兴趣的人,我很好奇这里的答案在执行时间上是如何比较的,下面是针对深度嵌套层次结构的结果。前三个结果是非递归的:

       user     system      total        real
Dir[*]: (34900 files stepped over 100 iterations)
0.110729   0.139060   0.249789 (  0.249961)
Dir.glob(*): (34900 files stepped over 100 iterations)
0.112104   0.142498   0.254602 (  0.254902)
Dir.entries(): (35600 files stepped over 100 iterations)
0.142441   0.149306   0.291747 (  0.291998)
Dir[**/*]: (2211600 files stepped over 100 iterations)
9.399860  15.802976  25.202836 ( 25.250166)
Dir.glob(**/*): (2211600 files stepped over 100 iterations)
9.335318  15.657782  24.993100 ( 25.006243)
Dir.entries() recursive walk: (2705500 files stepped over 100 iterations)
14.653018  18.602017  33.255035 ( 33.268056)
Dir.glob(**/*, File::FNM_DOTMATCH): (2705500 files stepped over 100 iterations)
12.178823  19.577409  31.756232 ( 31.767093)

它们是由以下基准测试脚本生成的:

require 'benchmark'
base_dir = "/path/to/dir/"
n = 100
Benchmark.bm do |x|
x.report("Dir[*]:") do
i = 0
n.times do
i = i + Dir["#{base_dir}*"].select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.glob(*):") do
i = 0
n.times do
i = i + Dir.glob("#{base_dir}/*").select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.entries():") do
i = 0
n.times do
i = i + Dir.entries(base_dir).select {|f| !File.directory? File.join(base_dir, f)}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir[**/*]:") do
i = 0
n.times do
i = i + Dir["#{base_dir}**/*"].select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.glob(**/*):") do
i = 0
n.times do
i = i + Dir.glob("#{base_dir}**/*").select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.entries() recursive walk:") do
i = 0
n.times do
def walk_dir(dir, result)
Dir.entries(dir).each do |file|
next if file == ".." || file == "."


path = File.join(dir, file)
if Dir.exist?(path)
walk_dir(path, result)
else
result << file
end
end
end
result = Array.new
walk_dir(base_dir, result)
i = i + result.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.glob(**/*, File::FNM_DOTMATCH):") do
i = 0
n.times do
i = i + Dir.glob("#{base_dir}**/*", File::FNM_DOTMATCH).select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
end

文件计数的差异是由于Dir.entries默认包含隐藏文件。在这种情况下,Dir.entries最终花费了更长的时间,因为需要重建文件的绝对路径以确定文件是否是目录,但即使没有这一点,它仍然比递归情况下的其他选项花费的时间更长。这都是在OSX上使用ruby 2.5.1完成的。

在IRB上下文中,您可以使用以下命令获取当前目录中的文件:

file_names = `ls`.split("\n")

你也可以在其他目录上这样做:

file_names = `ls ~/Documents`.split("\n")

一个简单的方法是:

dir = './' # desired directory
files = Dir.glob(File.join(dir, '**', '*')).select{|file| File.file?(file)}


files.each do |f|
puts f
end

这段代码只返回带扩展名的文件名(没有全局路径)

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

=比;[file_1。Rb, file_2.html, file_3.js]

当加载操作目录中的所有文件名时,您可以使用

Dir.glob("*)

这将返回应用程序正在运行的上下文中的所有文件(注意,对于Rails,这是应用程序的顶级目录)

你可以做额外的匹配和递归搜索找到这里https://ruby-doc.org/core-2.7.1/Dir.html#method-c-glob

如果你用空格创建目录:

mkdir "a b"
touch "a b/c"

你不需要转义目录名,它会自动完成:

p Dir["a b/*"] # => ["a b/c"]