Results 1 to 7 of 7
  1. #1
    Join Date
    Sep 2004
    Posts
    4

    Unanswered: Print Directory Tree

    I'd like to write a program to read a directory and then print the contents of that directory, along with any subdirectories and their files. For example, a directory with past newsletters in it that includes subdirectories for January, February, March, etc. So that it would display something like this:

    Newsletters:
    January-
    week1.htm
    week2.htm
    week3.htm
    week4.htm
    February-
    week1.htm
    week2.htm
    week3.htm
    week4.htm
    March-
    week1.htm
    week2.htm
    week3.htm
    week4.htm

    I can get it to display the contents of a folder with the code below, but is there an easy way to display multiple subdirectories like this, and have it not be dependant on specific subdirectory names?

    Code:
    #!/usr/bin/perl
    
    $dirtoget="/home/yourname/www/images/";
    opendir(IMD, $dirtoget) || die("Cannot open directory");
    @thefiles= readdir(IMD);
    closedir(IMD);
    
    print "Content-type: text/html\n\n";
    print "<HTML><BODY>";
    
    foreach $f (@thefiles)
    {
         print "$f<BR>";
    }
    
    print "</BODY></HTML>";

  2. #2
    Join Date
    Jun 2004
    Location
    Nowhere Near You
    Posts
    89
    Use a module called "File::Find". With it traversing the directory tree is a piece of cake!

  3. #3
    Join Date
    Sep 2004
    Posts
    4
    That looks pretty slick, but I'm a little confused by the man page. Can you give me an example? Most of what I'm finding is for search and replace. I just want to display the file names in blocks by directory name.

    Thanks.

  4. #4
    Join Date
    Jun 2004
    Location
    Nowhere Near You
    Posts
    89
    Perhaps this will do as an example?
    Code:
    #!\user\bin\perl -w
    
    use CGI;
    use File::Find;
    use File::Basename;
    
      # Current directory if nothing else was specified
      @ARGV=qw(.) unless @ARGV;
      my($s_Report)='report.html';
    
      # Set up @ARGV to minimize problems
      # Set args up Unix style with trailing '/'
      map {s|\\|/|g; $_.="/" unless (m|/$|)} @ARGV;
      @ARGV=sort @ARGV;
      for (my($index)=$#ARGV; $index > 0; $index--) {
        if ($ARGV[$index] =~ m|^$ARGV[$index-1]|i) {
          splice(@ARGV,$index,1);
           };
         };
      # "drive:/" is a special case (and "drive:\" doesn't work so)so ...
      map {s|:/$|:\\|} @ARGV;
      my(%h_ByExtension,%h_ByDirectory,$s_SizeOfChild);
      find ({wanted=>\&TreatThisFile,postprocess=>\&PostTreatThisDirectory,preprocess=>\&PreTreatThisDirectory},@ARGV);
    
      # Eliminate the offending parent directories:
      foreach (@ARGV) {
        delete $h_ByDirectory{$`} if (m|[^:/]+/$|);
         };
    
      # Create the report
    
      open (HTML,">$s_Report") or die "$!";
      my($s_Q)=CGI->new();
      print HTML $s_Q->header('text/html')
         ,$s_Q->start_html('Diskspace consumed by extension.')
         ;
      # Diskspace by extension
      my(@a_Headings)=qw(Extension TotalSize Number);
      my(@a_Rows);
      foreach my $s_Key (sort {$h_ByExtension{$b}[1]/$h_ByExtension{$b}[0] <=> $h_ByExtension{$a}[1]/$h_ByExtension{$a}[0]} keys %h_ByExtension) {
        push(@a_Rows,$s_Q->th("*$s_Key").$s_Q->td([WithCommas($h_ByExtension{$s_Key}[1]),$h_ByExtension{$s_Key}[0]]));
         };
      print HTML $s_Q->h1('Average diskspace consumed per file by extension:')
         ,$s_Q->table({-border=>3},$s_Q->Tr([$s_Q->th(\@a_Headings),@a_Rows]))
         ;
    
      # Diskspace by directory
      (@a_Headings)=qw(Directory SizeOfChildren Size Number);
      my($temp);(@a_Rows)=();
      foreach my $s_Key (sort {($h_ByDirectory{$b}[0] ? $h_ByDirectory{$b}[1]/$h_ByDirectory{$b}[0] : 0) <=> ($h_ByDirectory{$a}[0] ? $h_ByDirectory{$a}[1]/$h_ByDirectory{$a}[0] : 0)} keys %h_ByDirectory) {
        ($temp=$s_Key)=~ s|:[/\\]*|:/|;
        push(@a_Rows,$s_Q->th("$temp").$s_Q->td([WithCommas($h_ByDirectory{$s_Key}[2]),WithCommas($h_ByDirectory{$s_Key}[1]),$h_ByDirectory{$s_Key}[0]]));
         };
      print HTML $s_Q->h1('Average diskspace consumed per file by directory:')
         ,$s_Q->table({-border=>3},$s_Q->Tr([$s_Q->th(\@a_Headings),@a_Rows]))
         ,$s_Q->end_html
         ;
    
      close (HTML);
      my(@a_Log)=`$s_Report`;
    
      sub PreTreatThisDirectory {
        (@_)=sort {uc $a cmp uc $b} @_;
        # print join(';',@_)."\n";
        return @_;
         };
    
      sub PostTreatThisDirectory {
        #print 'PTTD '.$File::Find::name."\n";
        $h_ByDirectory{$`}[2]+=$s_SizeOfChild if ($File::Find::dir =~ m|[^:/]*$|);
         };
    
      sub TreatThisFile {
        #print 'TTF  '.$File::Find::name."\n";
        my($s_Path);
        if (-d ($s_Path=$File::Find::name)) {
          $h_ByDirectory{$s_Path.'/'}[0]=0;
          $h_ByDirectory{$s_Path.'/'}[1]=0;
           } else {
          my($s_Name,$s_Directory,$s_Extension)=fileparse($s_Path,'\.[^.]*');
          $h_ByExtension{"\U$s_Extension"}[0]++;
          $h_ByExtension{"\U$s_Extension"}[1]+=-s $_;
          $h_ByDirectory{$s_Directory}[0]++;
          $h_ByDirectory{$s_Directory}[1]+=-s $_;
          $s_SizeOfChild=$h_ByDirectory{$s_Directory}[1];
           };
         };
    
      sub WithCommas {
        $_=reverse $_[0];
        s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
        return scalar reverse;
        (my $s_Number=reverse $_[0])=~s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
        return scalar reverse $s_Number;
         };
    Most likely you don't have any interest in the predirectory treatment or postdirectory treatment.

  5. #5
    Join Date
    Jun 2004
    Location
    Nowhere Near You
    Posts
    89
    Simplified it by taking out the HTML stuff etc.
    Code:
    #!\user\bin\perl -w
    
    use File::Find;
    use File::Basename;
    use strict;
    use warnings;
    
      # Current directory if nothing else was specified
      @ARGV=qw(.) unless @ARGV;
    
      # Set up @ARGV to minimize problems
      # Set args up Unix style with trailing '/'
      map {s|\\|/|g; $_.="/" unless (m|/$|)} @ARGV;
      @ARGV=sort @ARGV;
      for (my($index)=$#ARGV; $index > 0; $index--) {
        if ($ARGV[$index] =~ m|^$ARGV[$index-1]|i) {
          splice(@ARGV,$index,1);
           };
         };
      # "drive:/" is a special case (and "drive:\" doesn't work so) so ...
      map {s|:/$|:\\|} @ARGV;
    
      # We want a reference to a hash (of directory) of hashes {of extensions} of arrays [of filenames]
      my($rhha,$f_DoNotInsert);
      find ({wanted=>\&TreatThisFile,preprocess=>\&PreTreatThisDirectory},@ARGV);
    
      foreach my $s_Directory (sort {uc $a cmp uc $b} keys %$rhha) { # In directory order
        # Print a directory name ?
        print "\n\n",$s_Directory,"\n";
        foreach my $s_Extension (sort {$a cmp $b} keys %{$rhha->{$s_Directory}}) { # In extension order (already uc'd)
          foreach my $s_Filename (sort {uc $a cmp uc $b} @{$rhha->{$s_Directory}{$s_Extension}}) { #
            print $s_Filename,"\n";
             };
           };
         };
    
      sub PreTreatThisDirectory {
        # Don't add this directory if it already has been added
        $f_DoNotInsert=exists $rhha->{$File::Find::dir};
        return @_;
         };
    
      sub TreatThisFile {
        my($s_Path);
        if (-d ($s_Path=$File::Find::name)) { # A directory ...
           } else { # A file ...
          my($s_Name,$s_Directory,$s_Extension)=fileparse($s_Path,'\.[^.]*');
          push(@{$rhha->{$s_Directory}{uc $s_Extension}},"$s_Name$s_Extension") unless ($f_DoNotInsert);
           };
         };

  6. #6
    Join Date
    Oct 2002
    Location
    Baghdad, Iraq
    Posts
    697
    Quote Originally Posted by gschimek
    I'd like to write a program to read a directory and then print the contents of that directory, along with any subdirectories and their files. For example, a directory with past newsletters in it that includes subdirectories for January, February, March, etc. So that it would display something like this:
    Ooh, I know this one:

    Code:
    ls -R

  7. #7
    Join Date
    Sep 2009
    Posts
    1
    Quite good directory treeview tool called print directory not a freeware but affortable. take a look at this tool....

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •