Unfortunately, I haven't worked out a few things like having it only read the files in the directories and excluding the subdirectories in directory_contents. I am getting duplicates.

Well, you're doing something a little different from the OP in this thread, listing all the data files along with the directories (instead of just the directories), so that does complicate things. To see where you're getting duplication and trouble, I think you'll want to use Data::Dumper 'Dumper'; and step through it with "perl -d". In the debugger, you can do p Dumper($some_variable_or_reference) to see what's happening with the data.

I think the correct way to make sure that you get the right structure in your output is to have the right structure be created by the "wanted" sub that you pass to File::Find. And that would be HoH, built recursively to have nested hash keys represent the nested directories. A special hash key "./" can be used to hold a reference to an array that contains the actual data files (if any) in a given directory.

Then for output, you just walk through the structure, indenting and including suitable html tags as you go. (And if you're really going to be outputting html, you should probably use HTML::Entities URI::Escape on the path strings.)

I cobbled this together based on another old post of mine that had to do with building a recursive hash structure (Re: seeking in hash data structure), and I'll confess that this took me longer than I'd like to admit. (It's tricky business to do recursion right, esp. if you don't do it very often.)

I'm sure there's one or more modules that could be used to simplify (or replace) this code. You might need to tweak it -- change "/" to "\", etc -- to make it work properly on windows (it works for me on macosx/unix/linux):

#!/usr/bin/perl use strict; use warnings; use diagnostics; use File::Find; use File::Basename; use HTML::Entities; @ARGV == 1 and -d $ARGV[0] or die "Usage: $0 path_name\n"; ( my $rootdir = shift ) =~ s{(?<!/)$}{/}; # make sure path ends with + "/" my %tree; $tree{$rootdir} = {}; find(\&wanted, $rootdir); print "<html>\n"; print_tree( \%tree, 0 ); print "</html>\n"; sub wanted { local $_ = $File::Find::name; if ( -f ) { # only work on data files (skip directories +) s{\Q$rootdir\E}{}; # remove the rootdir string from the pat +h name load_tree( $tree{$rootdir}, fileparse( $_ )); } } # recursively load the hash structure # (first call gets top-level hashref, and # file name, path from File::Basename::fileparse) sub load_tree { my ( $href, $name, $path ) = @_; my @dirs = split /\//, $path; push @dirs, '.' if ( $dirs[$#dirs] ne '.' ); my $key = shift @dirs; while ( @dirs and $key ne '.' and exists( $$href{"$key/"} )) { $href = $$href{"$key/"}; $key = shift @dirs; } if ( $key ne '.' and ! exists( $$href{"$key/"} )) { $$href{"$key/"} = {}; load_tree( $$href{"$key/"}, $name, join( '/', @dirs, '' )); } elsif ( $key eq '.' ) { push @{$$href{"$key/"}}, $name; } } # recursively print embedded lists sub print_tree { my ( $href, $indent ) = @_; printf( "%s<ul>\n", ' ' x $indent ); $indent++; if ( exists( $$href{'./'} )) { printf( "%s<li>%s</li>\n", ' ' x $indent, encode_entities( $_ + )) for ( @{$$href{'./'}} ); delete $$href{'./'}; } if ( keys %$href ) { for my $subdir ( sort keys %$href ) { printf( "%s<li>%s\n", ' ' x $indent, encode_entities( $su +bdir )); $indent++; print_tree( $$href{$subdir}, $indent ); $indent--; printf( "%s</li>\n", ' ' x $indent ); } } $indent--; printf( "%s</ul>\n", ' ' x $indent ); }
(Updated to use HTML::Entities instead of URI::Escape -- the latter was a wrong choice)

In reply to Re^5: Directory Tree Structure by graff
in thread Directory Tree Structure by rupesh

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.