http://www.perlmonks.org?node_id=219919

filmo has asked for the wisdom of the Perl Monks concerning the following question: (directories)

I've looked at File::Recurse and File::Find, but they both don't seem to handle sub-directories as I'd like. What I'm looking for is a nested hash of the directory, its files and sub-directories. i.e.
%result = ('top' =>[ file1, file2, file3, subdir1 => [sub_file1, sub_file2], subdir2 => [sub_file3, sub_subDIR =>[sub_sub_file1]], etc... ]);
If the top directory is "home" and one of the subdirectories is 'user1', I would like be able to access the files as
$result{'home'}[0] $result{'home'}{'user1'}[0] $result{'home'}{'user1'}[1], etc

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I get directory structure into a hash?
by Aristotle (Chancellor) on Dec 15, 2002 at 01:16 UTC

    Tie::Dir

    If you build your own, to avoid the problem merlyn you would probably do something like

    $result{home}{"."}[0] $result{home}{user1} $result{home}{user1}{"."}[0]
    A starting point:
    #!/usr/bin/perl -w use strict; use File::Find; use File::Spec::Functions qw(splitdir); use Data::Dumper; my %hash; find( sub { return if $_ eq '.' or $_ eq '..'; my $cursor = \%hash; $cursor = $cursor->{$_} ||= {} for splitdir $File::Find::dir; -d $_ ? $cursor->{$_} = { "." => [] } : push @{$cursor->{"."}}, $_; }, @ARGV); print Dumper \%hash;
Re: How do I get directory structure into a hash?
by BrowserUk (Patriarch) on Dec 15, 2002 at 07:58 UTC

    To use the test program, supply a path to the script on the command line, but choose a smallish one because Data::Dumper uses prodigious amounts of memory to dump the structure.

    The hashdir() function should be portable as far as it goes, but it doesn't check for things like symbolic links, devices etc...

    #! perl -slw use strict; use Data::Dumper; sub hashdir{ my $dir = shift; opendir my $dh, $dir or die $!; my $tree = {}->{$dir} = {}; while( my $file = readdir($dh) ) { next if $file =~ m[^\.{1,2}$]; my $path = $dir .'/' . $file; $tree->{$file} = hashdir($path), next if -d $path; push @{$tree->{'.'}}, $file; } return $tree; } my $tree = hashdir( shift ); print Dumper $tree;
Re: How do I get directory structure into a hash?
by merlyn (Sage) on Dec 15, 2002 at 00:17 UTC
    $result{'home'}[0] $result{'home'}{'user1'}[0]
    That's never gonna work. $result{'home'} cannot be both a hashref and an arrayref.
Re: How do I get directory structure into a hash?
by filmo (Scribe) on Dec 15, 2002 at 01:01 UTC
    Okay, so my structure is a bit messed up. :O
    So how do I get:
    $result{'home'}{'file1'} $result{'home'}{'user1'}{'file2'} $result{'home'}{'user1'}{'file3'} $result{'home'}{'user2'}{'subdir'}{'file4'} etc..
Re: How do I get directory structure into a hash?
by BrowserUk (Patriarch) on Dec 15, 2002 at 07:57 UTC

    To use the test program, supply a path to the script on the command line, but choose a smallish one because Data::Dumper uses prodigious amounts of memory to dump the structure.

    The hashdir() function should be portable as far as it goes, but it doesn't check for things like symbolic links, devices etc...

    #! perl -slw use strict; use Data::Dumper; sub hashdir{ my $dir = shift; opendir my $dh, $dir or die $!; my $tree = {}->{$dir} = {}; while( my $file = readdir($dh) ) { next if $file =~ m[^\.{1,2}$]; my $path = $dir .'/' . $file; $tree->{$file} = hashdir($path), next if -d $path; push @{$tree->{'.'}}, $file; } return $tree; } my $tree = hashdir( shift ); print Dumper $tree;

    Originally posted as a Categorized Answer.

Re: How do I get directory structure into a hash?
by anandsridharan (Initiate) on Nov 29, 2011 at 04:06 UTC
    The solution by aristotle works good. The only problem i am facing is there the hash is something like this.. $VAR1 = { '' => { 'home' => { Why am i getting an empty key? I don't know how to access the hash now? Can anyone help me with this?

    Originally posted as a Categorized Answer.

Re: How do I get directory structure into a hash?
by anandsridharan (Initiate) on Nov 29, 2011 at 04:17 UTC
    Sorry about my previous question. I wasn't clear. The actual question was how to avoid the empty key?

    Originally posted as a Categorized Answer.