Ruby Create Recursive Directory Tree Ruby Create Recursive Directory Tree json json

Ruby Create Recursive Directory Tree


You probably want something like this (untested):

def directory_hash(path, name=nil)  data = {:data => (name || path)}  data[:children] = children = []  Dir.foreach(path) do |entry|    next if (entry == '..' || entry == '.')    full_path = File.join(path, entry)    if File.directory?(full_path)      children << directory_hash(full_path, entry)    else      children << entry    end  end  return dataend

Recursively walk down the tree, building up a hash. Turn it into json with your favourite serialisation library.


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]]]  endend

(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 treepaths.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 argumentdef traverse_with_path tree, path = [], &block  path += [tree[:name]]  yield path  tree[:children].each{|c| traverse_with_path c, path, &block} if tree[:children]endtraverse_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| # for each path part, create a child of current node      acc2[dir] ||= {} # and pass it as new current node    end    acc  }

So, for the following structure:

#$ mkdir -p foo/bar#$ mkdir -p baz/boo/bee#$ mkdir -p baz/goo

code above returns this hash:

{  "baz"=>{    "boo"=>{      "bee"=>{}},    "goo"=>{}},  "foo"=>{    "bar"=>{}}}

Hope you'll manage to suit it to your needs.


Ruby's Find module (require 'find') is minimalist but handles directory recursion well: http://www.ruby-doc.org/stdlib/libdoc/find/rdoc/classes/Find.html