Alex Rivera | Logout

Ruby Create Recursive Directory Tree

Asked 2011-04-02T01:27:52.967
12

I need to recursively traverse a directory and create a tree to be used with the jsTree control. The control accepts a JSON format like so. I need some ruby magic to make this happen cleanly and quickly.

Any help is appreciated.

Edit
Report

1 Answer

7

First take your tree, convert it to a list of paths to leaves, similar to:

def leaves_paths tree
  if tree[:children]
    tree[:children].inject([]){|acc, c|
      leaves_paths(c).each{|p|
        acc += [[tree[:name]] + p]
      }
      acc
    }
  else
    [[tree[:name]]]
  end
end

(Not sure if above exactly follows your jsTree structure, but the principle is the same.)

Here's a sample of input and output:

tree = {name: 'foo', children: [
      {name: 'bar'},
      {name: 'baz', children: [
        {name: 'boo'}, 
        {name: 'zoo', children: [
          {name: 'goo'}
        ]}
      ]}
    ]}

p leaves_paths tree
#=> [["foo", "bar"], ["foo", "baz", "boo"], ["foo", "baz", "zoo", "goo"]]

Then, for each path, call FileUtils#mkdir_p:

paths = leaves_paths tree
paths.each do |path|
  FileUtils.mkdir_p(File.join(*path))
end

And you should be ok.

Edit: Simpler version:

You don't need to create list of leaves, just traverse whole tree and create a directory for every node:

# executes block on each tree node, recursively, passing the path to the block as argument
def traverse_with_path tree, path = [], &block
  path += [tree[:name]]
  yield path
  tree[:children].each{|c| traverse_with_path c, path, &block} if tree[:children]
end

traverse_with_path tree do |path|
  FileUtils.mkdir(File.join(*path))
end

Edit2:

Oh, sorry, I misunderstood. So, here's a way to make a Hash based on directory tree on disk:

Dir.glob('**/*'). # get all files below current dir
  select{|f|
    File.directory?(f) # only directories we need
  }.map{|path|
    path.split '/' # split to parts
  }.inject({}){|acc, path| # start with empty hash
    path.inject(acc) do |acc2,dir| 
answered 2011-04-02T05:29:20.653

Your Answer