in reply to Re: directory tree to hash of arrays
in thread directory tree to hash of arrays

Thanks...I guess I thought it was clearer than it actually was. What I wanted was similar to what you provided...but instead of each key being the file name, I want to be able to have a series of hashes in an array...such that it would be populated like:

The place I get lost in the code at the bottom is that the hash is returned...but I don't see how to take that and push it onto an array with the way the code was written

{name => 'pm_multi_line_match.pl', size => 1025}, 'pm_multi_mod_distro_test' => { 'My-Example' => { {name => 'Build.PL', size => 651}, ...etc
#!/usr/bin/env perl use strict; use warnings; use File::Find; use Data::Dumper; my $rootDir = '/tmp/somedir'; $Data::Dumper::Indent = 1; build_tree(my $tree, $rootDir); print Dumper($tree); sub build_tree { my $node = $_[0] = {}; my @s; find( sub { push @$node, (pop @s)->[1] while @s and $File::Find::dir ne $s[-1] +[0]; $node->{'name'} = $_ if -f; $node->{'size'} = -s if -f; # Here is where I am lost...How do I get this pushed into an array +? return $node if -f; push @s, [ $File::Find::name, $node ]; $node = $node->{$_} = {}; }, $_[1]); $_[0]{$_[1]} = delete $_[0]{'.'}; }

Replies are listed 'Best First'.
Re^3: directory tree to hash of arrays
by kcott (Archbishop) on Mar 08, 2014 at 02:17 UTC
    "What I wanted was similar to what you provided...but instead of each key being the file name, I want to be able to have a series of hashes in an array...such that it would be populated like:"

    You've forgotten to post the part that tells us what "it would be populated like"!

    If it was supposed to be this (which appears after the next paragraph):

    {name => 'pm_multi_line_match.pl', size => 1025}, 'pm_multi_mod_distro_test' => { 'My-Example' => { {name => 'Build.PL', size => 651}, ...etc

    then I'm left convinced that you don't really have a clear picture of the data structure you want.

    • What you've posted there has no container: what structure holds that data?
    • It starts with a hashref: was there supposed to be a key before it?
    • The next line has a key ('pm_multi_mod_distro_test') whose value is a hashref.
    • That hashref has a key ('My-Example') whose value is a hashref.
    • That hashref has no keys. You show another hashref where the key should be.
    • Basically, this is not a Perl data structure!

    I suggest the first thing you do is follow the link I already gave you ("perldsc - Perl Data Structures Cookbook") and learn about Perl data structures.

    When you've done that, tell us exactly, and in full (between <code>...</code> tags), what Perl data structure you'd like to generate from this directory structure (assuming all files have a size of 99):

    dir_A +-file_B +-dir_C +-file_D +-dir_E +-file_F +-file_G +-file_H

    When we know what your goal is, we can help you to achieve it.

    -- Ken

      I am fairly well familiar with how a hash and an array work...as well as a hash or arrays or vice-versa. I simply copied a snippet of your response. What I am looking for is a structure that will lend itself well to translation to JSON for display within a web application directory tree:

      $VAR1 = { '/tmp/dir1' => { 'innerdir1' => [{'name' => 'file1', 'size' => 12345}, {'name' +=> 'file2', 'size' => 1223}] } };

        That's a little inconsistent. Your outer dir is a hashref while your inner dir is an arrayref. Furthermore in some places (directories) you use the name as a key and in other places (files) as a value.

        I agree with kcott - it's always better to plan your data structure in detail first before considering the minutiae of how to construct it.

      Sorry if this appears as a double...I updated the original post...but wasn't sure if that would bubble up to you, so here is the same content

      Here is the current code, which is not doing what I want it to, and am having trouble wrapping my head around how to get to the structure I want to get. First, the data structure I want:

      my @dk = ( {data => [ { text => 'data', data => { spriteCssClass => 'folder', 'fullPath' => '/data' }, contents => [ { text => 'raw', data => { spriteCssClass => 'folder', fullPath => '/data/raw' }, contents => [ { text => 'file1.csv', data => { spriteCssClass => 'csv +', fullPath => '/data/raw +/file1.csv', size => '12345' } }, { text => 'file2.csv', data => { spriteCssClass => 'csv +', fullPath => '/data/raw +/file2.csv', size => '123' } } ] }, { text => 'rdf', data => { spriteCssClass => 'folder', fullPath => '/data/rdf' }, contents => [ { text => 'file1.rdf', data => { spriteCssClass => 'rdf +', fullPath => '/data/raw +/file1.rdf', size => '123456' } }, { text => 'file2.csv', data => { spriteCssClass => 'rdf +', fullPath => '/data/raw +/file2.rdf', size => '1235' } } ] } ], } ] });

      Now, the code...which is as far as I have gotten, modifying the previously mentioned code and reference Here.

      sub _directoryTree { my ($directory,$filter) = @_; my (@files,@dirs); find(sub{ push @files, $File::Find::name; },$directory); foreach my $file(@files) { chomp $file; my $ref = \@dirs; my $truncated = $file; $truncated =~ s/^$filter//; foreach my $dir ( split /\//,$truncated ) { my $i = 0; next if $dir eq ''; $i++ while ( $ref->[$i] and $ref->[$i]{name} ne $dir ); my $r; if (-f $file) { my ($ext,$spriteclass); if ($file =~ /\.(\w+)$/) { $ext = $1; if ($ext eq 'html') { $spriteclass = 'html'; } elsif($ext =~ m/png|jpg|jpeg|gif|ico/) { $spriteclass = 'image'; } elsif($ext eq 'pdf') { $spriteclass = 'pdf'; } else { $spriteclass = 'html'; } } $r= $ref->[$i] ||= {'text' => $dir, 'data' => { 'spriteCssClass' => $spritecla +ss, 'fullPath' => $file, 'id' => $dir, 'size' => (-s $file), 'type' => $ext } } unless $dir =~ m/^\./; #, 'access +ed' => ctime(stat($file)->atime) } else { $r= $ref->[$i] ||= {'text' => $dir, 'files' => [], 'data' => { 'spriteCssClass' => 'folder', 'fullPath' => $file, 'id' => $dir, 'size' => 0, 'type' => 'folder' } }; } $ref = $r->{'files'}; } } return \@dirs; }
        "Here is the current code, which is not doing what I want it to, and am having trouble wrapping my head around how to get to the structure I want to get."

        Your "current code" is just a subroutine definition. You don't show how, or in what context, you're calling it. You don't say how it's behaving differently from your expections or whether it's generating error or warning messages. You don't indicate which part, or parts, you're specifically having difficulties with ("wrapping my head around"). I've already provided you with the link to "How do I post a question effectively?" in this thread: here it is again, please read it this time and follow its guidelines in any future postings.

        "First, the data structure I want:"

        So, you want an array with a single element which is a hashref; that hashref having a single key/value pair, the value being an arrayref; that arrayref having a single element which is a hashref; ... In some places you want a key called 'data' to have a value which is an arrayref and in other places you want a key with same name to have a value which is an hashref. Can you explain why you want a structure like that and how you propose to use it?

        I asked you to provide the data structure you'd like to generate from a fairly simple directory structure. You've refused to do that! Why?

        What you've posted is not related to any directory structure you've shown and is peppered with meaningless noise. For instance, am I supposed to know what "spriteCssClass" is?

        I'm not convinced that you know what data structure you actually want. This would be the reason why you're having difficulties writing code to generate it.

        About the only help I can provide you with at this time is to show a possible data structure. This is an example of what I was expecting from you.

        { name => 'dir_A', subs => [ { name => 'file_B', size => 99, }, { name => 'dir_C', subs => [ { name => 'file_D', size => 99, }, { name => 'dir_E', subs => [ { name => 'file_F', size => 99, }, ], }, { name => 'file_G', size => 99, }, ], }, { name => 'file_H', size => 99, }, ], }

        Once you get the structure right, you can add whatever other information you want (file types, permissions, modification times, etc.). But, you need to get the structure right first!

        -- Ken