jkeenan1 has asked for the wisdom of the Perl Monks concerning the following question:

This question falls into the Stop Me Before I Write Another Module department. Suppose I have a multi-dimensional hash like this:

my %structure = ( dirs => { albemarle => { dirs => { chatauqua => {}, cattaraugus => {}, }, files => [ qw( washington adams jefferson ) ], }, beverly => { dirs => { ataturk => {}, bonaparte => {}, }, files => [ qw( madison monroe jackson ) ], }, cortelyou => { dirs => { peoria => {}, paducah => {}, }, files => [ qw( vanburen harrison tyler ) ], }, }, files => [ qw( alpha beta gamma ) ], );

I would like to pass a reference to this hash to a function which creates directories and files named and structured as above.

my $return_value = create_structure(\%structure);

The function would create directories and files are needed, leaving already existing directories and files with the same names intact. The return value would be a reference to some data structure that would report, e.g., how many directories and files were created.

This would be useful for me during testing. I did a Super Search of this site, searched CPAN and googled -- but didn't turn anything up. Does anyone know if such functionality has already been written?

Thank you very much.

Jim Keenan

Replies are listed 'Best First'.
Re: Recursive mkdir: is there already a module for this?
by GrandFather (Saint) on Jun 17, 2006 at 00:50 UTC

    File::Path has mkpath which recursively creates directory paths may be some of what you need, but would need a little wrapping up to do the full job.


    DWIM is Perl's answer to Gödel
      Thank you both!

      Jim Keenan
Re: Recursive mkdir: is there already a module for this?
by Joost (Canon) on Jun 17, 2006 at 00:48 UTC
Re: Recursive mkdir: is there already a module for this?
by GrandFather (Saint) on Jun 17, 2006 at 01:08 UTC

    An implementation of createStructure:

    use strict; use warnings; use File::Path; my %structure = ( dirs => { albemarle => { dirs => { chatauqua => {}, cattaraugus => {}, }, files => [ qw( washington adams jefferson ) ], }, beverly => { dirs => { ataturk => {}, bonaparte => {}, }, files => [ qw( madison monroe jackson ) ], }, cortelyou => { dirs => { peoria => {}, paducah => {}, }, files => [ qw( vanburen harrison tyler ) ], }, }, files => [ qw( alpha beta gamma ) ], ); createStructure ('./delme', \%structure); sub createStructure { my ($root, $hash) = @_; mkdir ($root) if ! -e $root; return if ! defined $root || ! keys %$hash; if (exists $hash->{dirs}) { for my $dir (keys %{$hash->{dirs}}) { createStructure ("$root/$dir", $hash->{dirs}{$dir}); } } if (exists $hash->{files}) { for my $file (@{$hash->{files}}) { next if -e "$root/$file"; open NEWFILE, '>', "$root/$file"; close NEWFILE; } } }

    DWIM is Perl's answer to Gödel
Re: Recursive mkdir: is there already a module for this?
by roboticus (Chancellor) on Jun 17, 2006 at 01:12 UTC
    jkeenan1:

    ...but just in case you were insane enough to create it, it might look something like this:

    #!/usr/bin/perl -w use strict; use warnings; sub funky_make_tree { my $tree_hr = shift or return; for my $dirname (keys %{$tree_hr->{"dirs"}}) { print "Creating dir: ", $dirname, "\n"; mkdir $dirname; chdir $dirname; &funky_make_tree($tree_hr->{"dirs"}{$dirname}); print "Done with dir: ", $dirname, "\n"; chdir ".."; } for my $filename (@{$tree_hr->{"files"}}) { print "Creating file: ", $filename, "\n"; open OUT, '>', $filename or die "ARGH!"; print OUT $filename, "\n"; close OUT; } } my %structure = ( dirs => { albemarle => { dirs => { chatauqua => {}, cattaraugus => {}, }, files => [ qw( washington adams jefferson ) ], }, beverly => { dirs => { ataturk => {}, bonaparte => {}, }, files => [ qw( madison monroe jackson ) ], }, cortelyou => { dirs => { peoria => {}, paducah => {}, }, files => [ qw( vanburen harrison tyler ) ], }, }, files => [ qw( alpha beta gamma ) ], ); &funky_make_tree(\%structure);
    (Yep, I tested it...)

    Update: And I was a bit slower on the draw than Grandpops....

    --roboticus