Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
ls_r: recursively list (and process) directories
Return a hash of directory contents, recursively.
Given a directory structure like this:
a/
|-- b.txt
`-- c/
|-- d.txt
`-- e/
`ls_r( Pathname.new("a") )` will produce:
{ <Pathname:a> => {
<Pathname:a/b.txt> => nil,
<Pathname:a/c> => {
<Pathname:a/c/d.txt> => nil,
<Pathname:a/c/e> => {}
}
}
}
The path arg must be an instance of Pathname.
If a block is given, each Pathname will be passed to the block
and the result used in the hash instead of the Pathname. This
way, you can process the results as they are built, so you get a
hash of things besides Pathnames.
If any key is nil, that key and its value are discarded from the
final result. That means you can filter results by having the
block return nil for files/directories you don't want.
Symlinks are not followed.
#
# Copyright 2009 John Croisant
#
# This snippet is licensed under the following terms:
#
# DO WHATEVER YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
# 0. You just DO WHATEVER YOU WANT TO.
#
def ls_r( path, &block )
new_path = path
if block_given?
new_path = block.call(path)
return {} if new_path.nil?
end
children = nil
if path.directory?
# Call this method on each child. Makes an array of hashes.
children = path.children.collect{ |child|
ls_r( child, &block )
}
# Combine the array of hashes into a single hash.
# But ignore any children that are nil.
children = children.reduce({}){ |mem,child_hash|
mem.merge!( child_hash.reject{ |k,v| k.nil? } )
mem
}
end
{ new_path => children }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment