lengge@chx400.switch.ch (Thomas Lenggenhager) (10/29/90)
I am just a beginner with perl. I use it on a SUN 4/490, the version is $Header: perly.c,v 3.0.1.8 90/10/16 10:14:20 lwall Locked $ Patch level: 36 This is my first perl program which should list all file entries of a directory recursively. However what it does is listing the files of the directory I give as input and the files of the first subdirectory but then the program stops! It seems to me, that some variables are not recovered correctly on returning from the subroutine, even by declaring them as local. I know that I could have that much more easily, but the main intent was to do some processing on each file of a sub-tree. Who can find the bug in my program, or who suggests a better solution to my problem. Many thanks for your help in advance, Thomas Lenggenhager SWITCH =============================================================================== Thomas Lenggenhager, SWITCH, ETH-Zentrum, CH-8092 Zurich, Switzerland INET: lenggenhager@verw.switch.ch | Tel: +41-1-261'8178 UUCP: ..!mcsun!chx400!lenggenhager | Fax: +41-1-261'8133 X.400: S=lenggenhager;OU=verw;O=switch;P=switch;A=arcom;C=ch Here follows my perl program: =============================================================================== # # Ask for directory name and list fileentries recursively # print "Directory: "; $dirname = <STDIN>; chop($dirname); do read_dir($dirname); exit; sub read_dir { # # Print all full filenames recursively to STDOUT # local($dirname) = @_; local($file, $filename); open($file, "/bin/ls -AF $dirname|") || return ; while (<$file>) { $filename = $_; chop($filename); if ($filename =~ s|/$||) { $dirname = $dirname . "/" . $filename; print $dirname, "/\n"; do read_dir($dirname); } else { print $dirname . "/" . $filename, "\n"; } } close($file); } -- =============================================================================== Thomas Lenggenhager, SWITCH, ETH-Zentrum, CH-8092 Zurich, Switzerland INET: lenggenhager@verw.switch.ch | Tel: +41-1-261'8178 UUCP: ..!mcsun!chx400!lenggenhager | Fax: +41-1-261'8133
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (10/30/90)
In article <1990Oct29.140931.5498@chx400.switch.ch> lengge@chx400.switch.ch (Thomas Lenggenhager) writes: : This is my first perl program which should list all file entries of a : directory recursively. However what it does is listing the files of the : directory I give as input and the files of the first subdirectory but : then the program stops! : It seems to me, that some variables are not recovered correctly on returning : from the subroutine, even by declaring them as local. : ... : Here follows my perl program: : =============================================================================== : # : # Ask for directory name and list fileentries recursively : # : print "Directory: "; : $dirname = <STDIN>; : chop($dirname); : do read_dir($dirname); : exit; : : sub read_dir { : # : # Print all full filenames recursively to STDOUT : # : local($dirname) = @_; : local($file, $filename); : open($file, "/bin/ls -AF $dirname|") || return ; : while (<$file>) { Okay, your problem is that you're thinking of $file as a filehandle. It isn't. It's a variable containing a filehandle--the null filehandle in this case. Declaring it local doesn't change this, so all your opens refer to the same filehandle. And so each open closes the previous one. What you want to do is local($file) = $seq++; open($file,...) where global $seq has been initialized to something like "FH001". Or, even better, don't use ls, but readdir(). Here's an example: #!/usr/bin/perl &dodir('.'); sub dodir { local($dir,$nlink) = @_; local($dev,$ino,$mode); ($dev,$ino,$mode,$nlink) = stat('.') unless $nlink; # first time opendir(DIR,'.') || die "Can't open $dir"; local(@filenames) = readdir(DIR); closedir(DIR); if ($nlink == 2) { # this dir has no subdirectories for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; print "$dir/$_\n"; } } else { # this dir has subdirectories for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; $name = "$dir/$_"; print $name,"\n"; ($dev,$ino,$mode,$nlink) = lstat($_); next unless -d _; chdir $_ || die "Can't cd to $name"; &dodir($name,$nlink); chdir '..'; } } } Larry
evans@decvax.dec.com (Marc Evans) (10/31/90)
In article <1990Oct29.140931.5498@chx400.switch.ch>, lengge@chx400.switch.ch (Thomas Lenggenhager) writes: |> Who can find the bug in my program, or who suggests a better solution to my |> problem. How about this instead: print "Directory: "; $dirname = <STDIN>; chop($dirname); do read_dir($dirname); exit 0; sub read_dir { local($dirname)=@_; opendir(DIR,$dirname); local(@entries)=readdir(DIR); closedir(DIR); local($entry); while ( $entry=shift(@entries) ) { next if ($entry eq "." || $entry eq ".."); if (-d $entry) { do read_dir("$dirname/$entry"); print "$dirname/\n"; } else { print "$dirname/$filename\n"; } } } -- =========================================================================== Marc Evans - WB1GRH - evans@decvax.DEC.COM | Synergytics (603)635-8876 Unix and X Software Contractor | 21 Hinds Ln, Pelham, NH 03076 ===========================================================================