Ruby中目录的一个转折点

时间:2012-10-02 04:54:38

标签: ruby algorithm directory performance processing-efficiency

我想做以下事情:

给定目录树:

Root
 |_dirA  
 |_dirB  
    |_file1  
    |_file2  
 |_dirC  
    |_dirD  
       |_dirE  
          |_file3  
          |_file4  
 |_dirF  
    |_dirG  
       |_file5  
       |_file6  
       |_file7  

...我想走目录树并构建一个数组,其中包含每个目录中至少有一个文件的第一个文件的路径。总体结构可能非常大,文件比目录多得多,所以我想捕获第一个文件的路径而不迭代给定目录中的所有文件。一个文件就足够了。对于上面的树,结果应该看起来像一个只包含:

的数组
  root/dirB/file1
  root/dirC/dirD/dirE/file3
  root/dirF/dirG/file5

我在红宝石中使用了Dir和Find选项,但我的方法感觉太强大了。

是否有一种有效的方法来编写此功能?感觉我在这里错过了一些红宝石技巧。

非常感谢!

这是我的方法:

root="/home/subtest/tsttree/"
Dir.chdir(root)
dir_list=Dir.glob("**/*/") #this invokes recursion
result=Array.new
dir_list.each do |d|
        Dir.chdir(root + d)
        Dir.open(Dir.pwd).each do |filename| 
            next if File.directory? filename  #some directories may contain only other directories so exclude them
            result.push(d + filename)
            break
        end
end
puts result

工作,但看起来很乱。

1 个答案:

答案 0 :(得分:0)

require 'pathname'

# My answer to stackoverflow question posted here:
# http://stackoverflow.com/questions/12684736/a-twist-on-directory-walking-in-ruby
class ShallowFinder
  def initialize(root)
    @matches = {}
    @root = Pathname(root)
  end

  def matches
    while match = next_file
      @matches[match.parent.to_s] = match
    end

    @matches.values
  end

  private

  def next_file
    @root.find do |entry|
      Find.prune if previously_matched?(entry)
      return entry if entry.file?
    end
    nil
  end

  def previously_matched?(entry)
    return unless entry.directory?
    @matches.key?(entry.to_s)
  end
end

puts ShallowFinder.new('Root').matches

输出:

根/ B / file1的

根/ C / d / E / file3的

根/ F / G / file5