in reply to Reading directory structure?

Here is some, potentially dangerous on UNIX (i.e. symlinks), code that will do what you want. I wrote this for my wife's office. It takes a given root dir, and makes an HTML "map" of it. you can modify this to fit your need. Of course the risk is that if you are on UNIX and you have a symlink, perl will open it as a directory and thusly you can potentially create an infinite loop with a symlink that links to its parent dir. Hope this code helps you out some.

I should add, there are some win32 specifics in there that don't really divert from the premise of your idea, but if usin the exact script on unix it probably won't come out right due to some win32 specifics.

P.S. I know the resultant HTML doesn't conform to 4.01 strict. I can make it conform but can't get the look and feel I want without breaking it (so don't harass too much for that)
#!/Perl/bin/perl use strict; use warnings; print "Enter the directory to map: "; chomp(my $dir = <STDIN>); #$dir = (length($dir) == 3? $dir:$dir."\\"); open(LOG,"> c:/log.html") or die "$!"; print LOG qq{<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; chars +et=ISO-8859-1"> <title>Map of:}.$dir.qq{</title> <style type="text/css"> h1 { font-weight:bold } li.file { font-style:italic; font-weight:normal } ul { list-style-type:disc } li.dir { list-style-type:none; font-weight:bold } </style> </head>}; print LOG qq{<h1>Map of }.$dir.qq{</h1><hr>\n}; print LOG qq{\n\n<ul>\n}; mapMe(\$dir); print LOG qq{</ul></html>}; close(LOG); ##Recursive routine to print out all the files & folders under a given + root node sub mapMe { #Get the parameter my ($handle) = @_; #Open the directory passed to the subroutine opendir(SPROUT,$$handle); #read the entries my @entries = readdir(SPROUT); #Close the directory closedir(SPROUT); my @list; my @dir; my @file; foreach (2..$#entries) { next if lc($entries[$_]) eq 'thumbs.db'; if(opendir(TEST,$$handle.(length($$handle) == 3? '':"\\").$ent +ries[$_]) and $entries[$_]) { closedir(TEST); push @dir,$$handle.(length($$handle) == 3? '':"\\").$entri +es[$_]; } elsif($entries[$_]) { push @file,$entries[$_]; } } push @list,sort @file; push @list,sort @dir; foreach my $item (@list) { #If its a directory and its not null if(opendir(TEST,$item)) { #Close the directory closedir(TEST); #print LOG qq{<ul>}; #Construct and write the log print LOG qq{\n<br><br><ul><li class="dir">}.$item.qq{<hr> +</li>\n}; #recurse the directory mapMe(\$item); } elsif($item) { $$handle =~ s{\\}{/}g; #print $handle; #Construct and write the log print LOG qq{<li class="file"> <a href="file:///}.$$handle.(length($$handle) + == 3? '':"\\").$item.qq{"\>}.$item.qq{</a></li>\n}; $$handle =~ s{/}{\\}g; } } print LOG qq{</ul><br>\n\n}; }

Grygonos

Replies are listed 'Best First'.
Re^2: Reading directory structure?
by bmann (Priest) on Oct 12, 2004 at 21:09 UTC
    Hi Grygonos,

    While it "gets the job done", a couple things jumped out at me that I felt were important enought to comment on.

    First of all, the big one: foreach (2..$#entries) Try running this on the root of your C drive, which doesn't have the "." and ".." entries. You'll miss the first two directories.

    opendir DIR, 'c:/'; print join "\n", (readdir(DIR))[0,1]; __END__ output on my system: 2dvtllhn.sys ADOBEAPP
    Also, it seems that . and .. are always listed first in the directory, but I've never seen it documented. I certainly wouldn't depend on it.

    Second, using the -d test instead of if(opendir(TEST,$item)) to test for a directory would be more efficient as well as more readable.

Re^2: Reading directory structure?
by gellyfish (Monsignor) on Oct 13, 2004 at 12:48 UTC