0

私は次のことをしたいと思います:

ディレクトリ ツリーが与えられた場合:

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

... ディレクトリ ツリーをたどって、少なくとも 1 つのファイルを含む各ディレクトリの最初のファイルへのパスを含む配列を作成したいと思います。全体的な構造は、ディレクトリよりも多くのファイルで非常に大きくなる可能性があるため、特定のディレクトリ内のすべてのファイルを反復処理せずに、最初のファイルへのパスのみを取得したいと考えています。1ファイルで十分です。上記のツリーの場合、結果は以下のみを含む配列のようになります。

  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/ファイル 1

ルート/C/D/E/file3

ルート/F/G/ファイル 5

于 2012-10-02T05:39:36.230 に答える