>hello
>i read through the recent thread concerning ways to pring the contents of
>a dir (most settled on readdir() opendir() etc).
>is there a way to readdir() recursively? i could find no mention in the
>online docs for readdir() and unfortunately don't have my camel book close
>at hand.
>
<etc>
You probably want to use File::Find to do this. It will protect you
from the exigencies of your filesystem.
Of course you can do this yourself if you must. The neatest way to do
this would be with the DirHandle module which will overcome the
nastiness you will encounter with caching Directory handle globs.
A quick example would be:
#!/develop/bin/perl
use DirHandle;
dodir("/htdoc");
sub dodir()
{
local $dir = shift;
my $dirhandle = new DirHandle($dir);
if($dirhandle)
{
while($file = $dirhandle->read)
{
next if ($file =~ /^\.{1,2}$/);
my $fullpath = $dir . "/" . $file;
if (-d $fullpath)
{
dodir($fullpath);
}
else
{
print $fullpath,"\n";
}
}
}
}
__END__
To see why you want to use DiHandle you might try this with the normal
opendir(),readdir() calls.
/J\
Jonathan Stowe
See the MetaFaq at http://www.btinternet.com/~gellyfish/resources/wwwfaq.htm
in any case, what i really want to do is to traverse a subtree
recursively, get the name and full path of all the files there, and their
last modified dates.
i would ultimately like to have a data file whose contexts look something
like this:
---datafile---
/home/jon/textfile Thu Jan 22 10:28:22 1998
/home/jon/anotherfile Mon Mar 23 11:59:37 1998
/home/jon/somedir/anothrefile Tue Feb 24 04:35:49 1998
------
etcetera. my current half-brained idea is to do something like:
$datefile='/home/jon/datefile';
open(DATEFILE,">$datefile") || die "can't open $datefile ";
print {DATEFILE} `ls -lR --full-time /home/jon/`;
and then parse the file name and date out of it. however, this is going
to be a great big pain in the arse because the output of the ls above is
quite ugly and doesn't print the full path to the file and the file
together. ie it prints the dir name, then below that the names of the
files in that dir.
i'm sure that there is a much better way to go about this - if you can
help, please also cc your reply to my email.
thanks
--
Jon Nathan
j...@blading.com
http://www.rupture.net/~jon
> in any case, what i really want to do is to traverse a subtree
> recursively, get the name and full path of all the files there, and their
> last modified dates.
This ought to give you some ideas. The technique for gleaning
human-readable file mod times comes from perlfaq5.
#!//c/perl/bin/perl -w
use File::Recurse; # available as part of File::Tools at CPAN
use File::stat; # standard lib
use Time::localtime; # standard lib
sub list_file {
$date_string = ctime(stat($_)->mtime);
print "$_ ($date_string)\n";
}
recurse \&list_file, '/usr/local/lib';
--
Jonathan Feinberg j...@pobox.com Sunny Brooklyn, NY
> hello
> i read through the recent thread concerning ways to pring the contents of
> a dir (most settled on readdir() opendir() etc).
> is there a way to readdir() recursively? i could find no mention in the
> online docs for readdir() and unfortunately don't have my camel book close
> at hand.
>
> in any case, what i really want to do is to traverse a subtree
> recursively, get the name and full path of all the files there, and their
> last modified dates.
Check out the following recursive routine. There are many possible
variations on this which would also work, and this one is not
necessarily the quickest, because the `map' and `grep' stuff could be
eliminated in favor of some manipulation within the `foreach' loop:
sub printDirRecursively {
my $dir = shift;
unless (defined($dir)) {
warn "undefined directory name";
return (undef);
}
unless (opendir(DIR, $dir)) {
warn "unable to open directory: $dir";
return (undef);
}
my @itemList = sort # ... if you want this sorted
map { "$dir/$_" }
grep { $_ !~ m/^\.\.?$/ }
readdir(DIR);
closedir(DIR); # close DIR before recursing
my $item;
foreach $item (@itemList) {
if (-d $item) {
printDirRecursively($item); ### note this recursive call ###
}
else {
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($item);
if (defined($mtime)) {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime($mtime);
printf("%04d/%02d/%02d-%02d:%02d:%02d -- %s\n",
$year + 1900, $mon + 1, $mday,
$hour, $min, $sec, $item);
}
else {
warn "unable to get modification time: $item";
}
}
}
return (undef);
}
printDirRecursively('.');
--
Lloyd Zusman l...@asfast.com
perl -e '$n=170;for($d=2;($d*$d)<=$n;$d+=(1+($d%2))){for($t=0;($n%$d)==0;
$t++){$n=int($n/$d);}while($t-->0){push(@r,$d);}}if($n>1){push(@r,$n);}
$x=0;map{$x+=(($_>0)?(1<<log($_-0.5)/log(2.0)+1):1)}@r;print"$x\n"'
>Of course you can do this yourself if you must. The neatest way to do
>this would be with the DirHandle module which will overcome the
>nastiness you will encounter with caching Directory handle globs.
Use of the DirHandle module is rarely needed (even the DirHandle
docs imply this).
>A quick example would be:
>
>#!/develop/bin/perl
>use DirHandle;
>dodir("/htdoc");
>sub dodir()
>{
> local $dir = shift;
> my $dirhandle = new DirHandle($dir);
> if($dirhandle)
> {
> while($file = $dirhandle->read)
> {
> next if ($file =~ /^\.{1,2}$/);
> my $fullpath = $dir . "/" . $file;
It is better to get the entire directory list into an array, close the
directory handle, and then iterate of the array. This avoids the need
having a have a unique directory handle, and to avoid the possibility
of running out of descriptors due to too many open files.
--ewh
--
Earl Hood | University of California: Irvine
eh...@medusa.acs.uci.edu | Electronic Loiterer
http://www.oac.uci.edu/indiv/ehood/ | Dabbler of SGML/WWW/Perl/MIME