Get names of all files from a folder with Ruby

后端 未结 19 2410
[愿得一人]
[愿得一人] 2020-11-29 14:57

I want to get all file names from a folder using Ruby.

19条回答
  •  悲哀的现实
    2020-11-29 15:52

    In addition to the suggestions in this thread, I wanted to mention that if you need to return dot files as well (.gitignore, etc), with Dir.glob you would need to include a flag as so: Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH) By default, Dir.entries includes dot files, as well as current a parent directories.

    For anyone interested, I was curious how the answers here compared to each other in execution time, here was the results against deeply nested hierarchy. The first three results are non-recursive:

           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)
    

    These were generated with the following benchmarking script:

    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
    

    The differences in file counts are due to Dir.entries including hidden files by default. Dir.entries ended up taking a bit longer in this case due to needing to rebuild the absolute path of the file to determine if a file was a directory, but even without that it was still taking consistently longer than the other options in the recursive case. This was all using ruby 2.5.1 on OSX.

提交回复
热议问题