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

Hi Monks!

I have this code here that does what I want, it prints the whole directory tree assigned in $input_dir, but the problem I am having right now is when it has to read a too big of a location, like the entire drive c:, it is timing out, taking too much time. Is there a way to optimize the code so it would print (display) only the first level of file(s) and (or) directories it finds in it's way, like in the c: drive as an exemple, and waits till the user clicks again to go deeper into the desired location instead of reading the whole thing at once?
Here is the code for you evaluation.<br
#!/perl/bin/perl -w use strict; use CGI qw(:header); use CGI::Carp qw(fatalsToBrowser); use CGI qw/:standard/; my $show = param("show"); #my $input_dir = $ARGV[0] || '.' ; my $input_dir = "c:"; print header(); print "<html> <head><title>Directory Tree Viewer</title> <script type=\"text/javascript\" src=\"aqtree3.js\"></script> <script type=\"text/javascript\" src=\"aqtree3clickable.js\"></script> <link rel=\"stylesheet\" href=\"aqtree3.css\"> <link rel=\"stylesheet\" href=\"aqtree3clickable.css\"> </head> <body> Start<br><form action=\"make_form.pl\" method=\"get\"> "; #print "<ul class=\"aqtree3clickable\">"; MAIN: { my @tree; dirwalk ($input_dir,\@tree); #print "L32-<OL>\n"; printtree(\@tree); #print "</OL>\n"; } sub dirwalk { my ($dir,$tree) = @_ ; push @{$tree},($dir =~ m#([^/]+$)#); opendir DIR, $dir || die "Couldnt open $dir - $!\n"; my @entries = grep !/^\.{1,2}$/, readdir(DIR); closedir (DIR); foreach my $item (@entries) { my $fullpath = "$dir/$item"; if ( -d $fullpath ) { dirwalk ( $fullpath,\@{$tree->[@{$tree}]}); } else { push @{$tree},$item; } } } sub printtree { my $tree = shift; my $c=-1; #print "<ul id=\"tree-checkmenu\" class=\"checktree\">"; #print "<li id=\"show-khtml\">"; print "<ul class=\"aqtree3clickable\"><li><a href=\"#\"><!--img src= +images/dir.gif border=0-->&nbsp;",shift @{$tree},"</a><!--/53--><br>\ +n"; #print "<span id=\"count-khtml\" class=\"count\"></span><ul id=\"tre +e-khtml\">"; #print "<OL>74\n"; foreach my $item ( @{$tree} ) { #print "<b>$item</b>"; $c++; if (ref $item eq "ARRAY" ) { printtree($item); } else { print "<ul><li><input type=checkbox name=\"first_path\" value +=\"$item\"><a href=\"#\">\n"; print $item,"<!--^$c-64--></a></li></ul>\n"; } } #print "95</OL>"; print "</li>"; print "</ul>"; } print "<br>End <input type=submit></form> </body> </html> ";

Thanks for the big help!

Replies are listed 'Best First'.
Re: Directory Tree Viewer
by jdporter (Paladin) on Sep 21, 2006 at 16:10 UTC

    Yes: Instead of your reinvented-wheel dirwalk sub, use the standard File::Find module. It has a prune function (actually a flag) which lets you bail out based on any criteria, such as depth.

    We're building the house of the future together.
      OK, I will be reading on it!
Re: Directory Tree Viewer
by planetscape (Chancellor) on Sep 22, 2006 at 01:15 UTC
      It's good, but in terms of speed there is no difference between my code and this one.