0

我想做以下事情:

给定一个目录树:

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

我在 ruby​​ 中使用过 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

有效,但看起来很乱。

4

1 回答 1

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

于 2012-10-02T05:39:36.230 回答