Re: Dynamic directory handles?
- From: "IanW" <whoever@xxxxxxxxxxxxx>
- Date: Thu, 22 Dec 2005 17:32:12 -0000
"Tad McClellan" <tadmc@xxxxxxxxxxxxxx> wrote in message
news:slrndqlck1.71n.tadmc@xxxxxxxxxxxxxxxxxxxxxxx
> IanW <whoever@xxxxxxxxxxxxx> wrote:
>
>> I have a chunk of code that counts files.dirs and size for a directory
>> tree.
>
>
> You have a whole bunch of problems, some big, some small.
oh dear.. I was worried that might happen! ;)
> I'll mention the lesser ones in comments about your code below,
> but the 3 big ones are:
>
> 1) You should always enable warnings (and strict) when
> developing Perl code.
>
> 2) You get a dynamic dirhandle the same way you get a dynamic
> filehandle, so:
>
> perldoc -q filehandle
>
> How can I make a filehandle local to a subroutine? How do I pass
> file-
> handles between subroutines? How do I make an array of filehandles?
>
> 3) There is an already-invented (and tested) wheel for doing
> recursive directory searching, the File::Find module.
The only thing that sometimes puts me off using modules for relatively
simple things like this, is that I wonder how much extra resources they use
or whether they compromise performance in some way. That is, File: Find must
be quite a sizable module with a stack of function/options, so couldn't that
mean lots more memory to run, or is that an incorrect presumption?
> You can read the module's docs with:
>
> perldoc File::Find
>
>
>>================
>> #use strict;
>
>
> You lose all of the benefits of that statement when you comment it out!
yes, I know - I had it commented out to double check that the script worked
without use strict.
>> my $basedir = "j:/files/sw-test";
>> my $fcount = 0;
>> my $fsize = 0;
>> my $dcount = 0;
>> dircount();
>>
>> sub dircount {
>> my($cdir) = shift;
>
>
> $cdir will be undef for the top-level call.
>
>
>> $cdir .= "/" if $cdir ne "";
>
>
> You have all of the path components separated already, so I'd
> paste the dir separator in myself on each usage instead of
> burying one inside of a variable's value.
there was a reason I did that, but I can't recall what it was now (bear with
me - it's nearly home-time and my brain is frazzled!)
>> my $dh = "DH" . length($cdir);
>> opendir($dh,"$basedir/$cdir");
>
>
> You get a dynamic dirhandle when the variable is undef.
>
> Your variable is not undef, so there is no dynamic dirhandle...
>
>
> You should always check the return value to see if you actually
> got what you asked for:
>
> opendir($dh,"$basedir/$cdir") or die "could not open '$basedir/$cdir'
> $!";
>
>
>> while(my $fl = readdir($dh)){
>> next if $fl =~ /^\.{1,2}$/;
>> if(-d "$basedir/$cdir$fl"){
>> $dcount++;
>> dircount("$cdir$fl");
>
>
> If $fl is a symlink to a "higher" directory, then your
> code will go into an infinite loop here.
it's a script that will only run on my Windows servers, so that wasn't an
issue
> Applying the minimum changes to fix (IMO) your code, I get:
>
> ------------------------
> #!/usr/bin/perl
> use warnings;
> use strict;
>
> my $basedir = '/home/tadmc/temp';
> my $fcount = 0;
> my $fsize = 0;
> my $dcount = 0;
> dircount();
>
> sub dircount {
> my($cdir) = shift || '';
that's a neat way of avoiding getting a warning (yes, I did have use
warnings in there for a while :-).. is there any particular reason you use
single quotes there instead of double quotes? I tend to use "" for pretty
much everything. Also, I don't ever seem to use "||" - "or" would work as
well in that scenario wouldn't it?
> opendir(my $dh,"$basedir/$cdir") or die "could not open dir $!";
> while(my $fl = readdir($dh)){
> next if $fl =~ /^\.{1,2}$/;
> if(-d "$basedir/$cdir/$fl"){
> $dcount++;
> dircount("$cdir/$fl");
> }
> else{
> $fcount++;
> $fsize += -s "$basedir/$cdir/$fl";
> }
> }
> close($dh);
> }
>
> print "$fcount files and $dcount directories totalling $fsize bytes in
> size\n";
> ------------------------
>
>
>
> Recasting it to use the tried-and-true module, I get:
>
> ------------------------
> #!/usr/bin/perl
> use warnings;
> use strict;
> use File::Find;
>
> my $basedir = '/home/tadmc/temp';
> my $fcount = 0;
> my $fsize = 0;
> my $dcount = 0;
> find( \&dircount, $basedir );
>
> sub dircount {
> return if $_ eq '.' or $_ eq '..';
> $dcount++ if -d;
> return unless -f; # only care about plain files at this point
> $fcount++;
> $fsize += -s;
> }
>
> print "$fcount files and $dcount directories totalling $fsize bytes in
> size\n";
> ------------------------
thanks
Ian
.
- Follow-Ups:
- Re: Dynamic directory handles?
- From: Tad McClellan
- Re: Dynamic directory handles?
- From: Paul Lalli
- Re: Dynamic directory handles?
- From: Tintin
- Re: Dynamic directory handles?
- From: Glenn Jackman
- Re: Dynamic directory handles?
- References:
- Dynamic directory handles?
- From: IanW
- Re: Dynamic directory handles?
- From: Tad McClellan
- Dynamic directory handles?
- Prev by Date: Re: CGI.pm not interactive at command line
- Next by Date: Re: Bit-Vector-6.4 on Cygwin
- Previous by thread: Re: Dynamic directory handles?
- Next by thread: Re: Dynamic directory handles?
- Index(es):
Relevant Pages
|