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

时间:2009-11-18 12:33:48

标签: ruby file directory filenames

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

19 个答案:

答案 0 :(得分:471)

您还有

的快捷方式选项
Dir["/path/to/search/*"]

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

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

答案 1 :(得分:154)

Dir.entries(folder)

示例:

Dir.entries(".")

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

答案 2 :(得分:86)

以下代码段会准确显示目录中文件的名称,跳过子目录和"."".."点缀文件夹:

Dir.entries("your/folder").select {|f| !File.directory? f}

答案 3 :(得分:31)

以递归方式获取所有文件(仅限严格文件):

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

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

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

替代解决方案

Dir.glob等基于模式的查找方法使用Find#find实际上更好。请参阅this answer to "One-liner to Recursively List Directories in Ruby?"

答案 4 :(得分:11)

这对我有用:

如果您不想要隐藏文件[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(您只需传递带有目录名称的变量),但它将返回基本名称直接,因此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 ) }
unix上的

[1] .dotfile,我不了解Windows

答案 5 :(得分:8)

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

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

答案 6 :(得分:8)

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

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

答案 7 :(得分:5)

在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

答案 8 :(得分:4)

在获取目录中的所有文件名时,此代码段可用于拒绝目录[>>> add_nulls2(5,5) '00005' >>> add_nulls2(0,5) '00000' >>> .]和以..

.

答案 9 :(得分:3)

这对我有用:

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

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

的原因

答案 10 :(得分:1)

如果您想获取一系列文件名包括符号链接,请使用

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

答案 11 :(得分:1)

除了此线程中的建议外,我想提到的是,如果您还需要返回点文件(.gitignore等),则使用Dir.glob时还需要包含一个标志: Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH) 默认情况下,Dir.entries包括点文件以及当前的父目录。

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

       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。

答案 12 :(得分:1)

您可能还想使用Rake::FileList(假设您有rake依赖项):

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

根据API:

  

FileLists很懒惰。给出一个可能的glob模式列表   要包含在文件列表中的文件,而不是搜索文件   在查找文件的结构中,FileList保存了后者的模式   使用

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

答案 13 :(得分:1)

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

答案 14 :(得分:0)

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

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

答案 15 :(得分:0)

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

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

您也可以在其他目录上执行此操作:

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

答案 16 :(得分:0)

一种简单的方法可能是:

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

files.each do |f|
    puts f
end

答案 17 :(得分:0)

此代码仅返回扩展名的文件名(无全局路径)

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

答案 18 :(得分:0)

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

Dir.glob("*)

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

您可以在https://ruby-doc.org/core-2.7.1/Dir.html#method-c-glob

处进行其他匹配和递归搜索