Herong's Tutorial Notes on Perl - Part A
Dr. Herong Yang, Version 4.09

Reading Directory Entries

Part:   1  2   3 

(Continued from previous part...)

Displaying Directory Tree - DirTree.pl

Both Unix and Windows systems organize file directories into a tree structure. The following program. DirTree.pl, shows you how to traverse the directory tree, and display directory entries:

#- DirTree.pl
#- Copyright (c) 1995 by Dr. Herong Yang
#
   ($dir) = @ARGV;
   $dir = "." unless $dir;
   &loopDir($dir, "");
   exit;
sub loopDir {
   local($dir, $margin) = @_;
   chdir($dir) || die "Cannot chdir to $dir\n";
   local(*DIR);
   opendir(DIR, ".");
   while ($f=readdir(DIR)) {
      next if ($f eq "." || $f eq "..");
      print "$margin$f\n";
      if (-d $f) {
         &loopDir($f,$margin."   ");
      }
   }
   closedir(DIR);
   chdir("..");
}

Be careful, don't try this program in the root directory. It will produce a very very long list of files and directories. I tried it on the working directory where I stored my Perl notes and programs, and I got the following:

>DirTree.pl ..
htm
   about.html
   active_perl.html
   book.css
   book_fo.xsl
   dot.gif
   help.html
   open.html
   opendir.html
   reference.html
   toc.html
   ...
src
   DirTree.pl
   hello.pl
   hello.prg
   opendir.pl
   ...

If you review DirTree.pl, you will see some interesting statements and techniques:

  • " $dir = "." unless $dir;" is used to assume a default directory, if nothing specified on the command line.
  • " local($dir, $margin) = @_;" is used to make $dir and $margin as local variables. This very important, since loopDir() is called recursively.
  • " local(*DIR);" is used to make DIR as local variable in any name spaces, including directory handle name space. In fact, this is the only way to make directory handle names local.
  • " if (-d $f) {" is used to test the directory entry to see if it is a directory.

Counting Files - DirCount.pl

My second of example of traversing directory tree is DirStats.pl. It collects several statistics of the specified directory tree:

#- DirCount.pl
#- Copyright (c) 1995 by Dr. Herong Yang
#
   ($dir, $extension) = @ARGV;
   $dir = "." unless $dir;
   $extension = "pl" unless $extension;
   $dirCount = 0;
   $fileCount = 0;
   $fileSize = 0;
   $otherCount = 0;
   $otherSize = 0;
   &loopDir($dir);
   print "Number of directories = $dirCount\n";
   print "Number of files with .$extension = $fileCount\n";
   print "Total size of files with .$extension = $fileSize\n";
   print "Number of other files = $otherCount\n";
   print "Total size of other files = $otherSize\n";
   exit;
sub loopDir {
   local($dir) = @_;
   chdir($dir) || die "Cannot chdir to $dir\n";
   $dirCount++;
   local(*DIR);
   opendir(DIR, ".");
   while ($f=readdir(DIR)) {
      next if ($f eq "." || $f eq "..");
      if (-d $f) {
         &loopDir($f,);
      } elsif ($f=~/\.$extension$/) {
         $fileCount++;
         $fileSize += -s $f;
      } else {
         $otherCount++;
         $otherSize += -s $f;
      }
   }
   closedir(DIR);
   chdir("..");
}

The first run is on my Perl notes working directory. The output shows that I have 5 Perl files in 5 directories with total size of 8437 bytes. And there are some other files in these directories:

>DirCount.pl ..
Number of directories = 5
Number of files with .pl = 5
Total size of files with .pl = 8437
Number of other files = 44
Total size of other files = 115580

Then I run my DirCount.pl on the Windows system directory to count how many executable files do we have the system:

>DirCount.pl c:\winnt exe
Number of directories = 353
Number of files with .exe = 975
Total size of files with .exe = 111390120
Number of other files = 10218
Total size of other files = 1376214106

(Continued on next part...)

Part:   1  2   3 

Dr. Herong Yang, updated in 2006
Herong's Tutorial Notes on Perl - Part A - Reading Directory Entries