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