I have this program that recurses through a directory structure building
Default.htm files. The idea here was to quickly generate a bunch of these
things to replace the default index listing you normally see. The part
that's giving me trouble is the navbar that should have a nested structure
like...
Food
Fruit
Apples
Oranges
Kiwi
Vegetables
Coffee
Critters
Cars
Rocks
So that if you are in /DocRoot/Food/Fruit you would see the above on the
left all properly linked yada yada. The code I've pasted in does this just
fine (I've removed a bunch of stuff to focus on the real problem) but only
on small directory structures. When I run it on something with 10 directory
levels, 3 or 4 subdirectories in each one, 20-30 files in each one, it zips
along for a few seconds then grinds to a halt, consumes all my physical
memory and begins swapping like mad.
I changed things around to not use the joinLists() function and to have
buildIndices() call itself rather than have getLinks call it and it works
fine. But I don't know why, hence the posting. Anyone feel like tackling
this?
Thanks!
Peter C.
------------------------------------------
#! perl
use strict;
use warnings;
use File::Copy;
use vars ('$rootDir');
#===========================================================================
====
# Main
#===========================================================================
====
my $baseURL = "engweb";
$rootDir = "d:/inetpub/wwwroot/$baseURL";
buildIndices($rootDir, "/$baseURL") or
die ("failed trying to build $rootDir\n");
exit 0;
#===========================================================================
====
# Functions
#===========================================================================
====
#---------------------------------------------------------------------------
----
# buildIndices($dir, $parentLinks)
#
# This function takes a document directory and builds the
# Default.htm file for it.
#
sub buildIndices {
my ($dir, $url, $parentLinks) = @_; #$parentLinks is an array ref.
my $cwd = (split /\\|\//, $dir)[-1];
print "currently working on $dir\n";
local $" = "\n"; #Set the list seperator to a new line.
#All we want is 2 things, a directory and an html file.
#Is that too much to ask for?
copy ("$rootDir\\Default.htm", "$dir\\Default.htm")
unless -T "$dir\\Default.htm";
unless (-d $dir and -T "$dir\\Default.htm") {
print "$dir is not a directory\n" unless -d $dir;
print "We couldn't put the Default.htm file in $dir\n"
unless -T "$dir\\Default.htm";
return 0;
}
my @curLinks = getLinks($dir, $url, $parentLinks);
#links should have a bunch of '<a href...' strings
#if we were given a parentLinks array splice these two together.
# if there were no subdirectories or files splice in an anonymous
# array that Just says "EMPTY"
my @links = ($parentLinks and $cwd) ?
joinLists (@curLinks ? \@curLinks :
["<DIV STYLE=\"margin:10\">",
"Empty", "</DIV>"],
$parentLinks, $cwd) :
@curLinks;
#there's just an inplace edit here...
#
#...
return 1; #one is good
}
#---------------------------------------------------------------------------
----
# getLinks($dir)
#
# loop through the directory entries and build a bunch of '<a href...'
# strings and stuff them in an array. If the entry is a directory call
# buildIndices($ent) on it.
#
sub getLinks {
my ($dir, $url, $parentLinks) = @_;
my @subDirs;
my @links = ();
my $link;
my $ent; #a thing for iterating over directory entries
my $cwd = (split /\\|\//, $dir)[-1];
opendir (DH, $dir) or
logItAndDie("Can't open the directory $rootDir,
status=$!\n");
while (defined ($ent = readdir(DH))) {
next if $ent =~ /^\./; #skip things with leading '.'
if (-d "$dir/$ent") {
#Add some spaces.
push @links, "<a
href=\"$url/$ent/Default.htm\">$ent</a><br>";
push @subDirs, "$dir/$ent"; #to be used in calls to
buildIndices
} elsif ($ent =~ /\.(htm|html|jsp|doc)$/) {
if (!($ent =~ /Default/)) { # Skip the
Default files
push @links, "<a
href=\"$url/$ent\">$ent</a><br>";
}
}
}
closedir(DH);
if (@links) {
unshift @links, "<DIV STYLE=\"margin:10\">";
push @links, "</DIV>";
}
my @completeLinks = ($cwd and $parentLinks) ?
joinLists (\@links, $parentLinks, $cwd) :
@links;
for (@subDirs) {
buildIndices($_, "$url/" . (split /\\|\//)[-1],
\@completeLinks)
or die;
}
return @links;
}
#---------------------------------------------------------------------------
----
# joinLists($subListRef, $masterListRef, $key)
#
# Add a sub list to the right point in the larger master list...
#
sub joinLists {
my ($subList, $masterList, $key) = @_;
return map {
if (/\Q$key/i) {
my $newEnt = $_; #don't want to taint
the masterlist
$newEnt =~ s/\Q$key\E(\/|\\)//i;
$newEnt, @$subList;
} else {
$_
}
} @$masterList if $masterList;
}
#===========================================================================
====
# End Functions
#===========================================================================
====