Software, web, and game design and development
Here's a little Ruby function I came up with today. I thought it might be useful to other people, so here it is.
# To the extent possible under law, the author (John Croisant) has # waived all copyright and related or neighboring rights to this work. # See: https://creativecommons.org/publicdomain/zero/1.0/ # Return a hash of directory contents, recursively. # # Given a directory structure like this: # # a/ # |-- b.txt # `-- c/ # |-- d.txt # `-- e/ # # `ls_r("a")` will produce: # # { <Pathname:a> => { # <Pathname:a/b.txt> => nil, # <Pathname:a/c> => { # <Pathname:a/c/d.txt> => nil, # <Pathname:a/c/e> => {} # } # } # } # # 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 the block returns nil, that entry and its children are discarded # from the final result. # # Symlinks are not followed. # def ls_r( path, &block ) require 'pathname' path = Pathname.new(path) unless path.is_a? Pathname new_path = path if block_given? new_path = yield path return {} if new_path.nil? end children = nil if path.directory? # Call ls_r recursively on each child. Makes an array of hashes. children = path.children.map { |child| ls_r( child, &block ) } # Combine the array of hashes into a single hash. # But ignore any children with a nil key. children = children.reduce({}){ |result, child| result.merge!( child.reject{ |k,v| k.nil? } ) } end { new_path => children } end