Nick D Montpetit wrote:
> 
> Hi Everyone!

Hello,

> I'm fairly new to Perl, and completely new to submitting to the list, so
> please be easy on me.  :-)

I'll try.

> The purpose of the code I wrote (listed below) is to go through the current
> directory and all of its subdirectories and report the filename, size and
> age of the x largest files, where x depends on the argument supplied on the
> command line and the number of files in the directory.  I'm sure there's an
> easier way to do this with a UNIX utility (or with Perl), but this program
> has been a good learning experience for me.
> 
> The code below runs without any syntax errors, but File::Find (which I love
> and use frequently) or the -e file test doesn't give the results I expect.
> Specifically, my (explicit) checks show that the test in line 11 does not
> always evaluate to TRUE for values of $_ corresponding to legitimate (i.e.,
> existing and size > 0) files, which means I'm missing files that should be
> in my final output.  If I change line 11for debugging purposes to simply
> 
> if ($_){
> 
> all files (including the previously missed ones) are printed out (also
> along with the directories now) as expected, but for the files that would
> not have passed the (-e $_) test, the values assigned for filesize and age
> in line 12 are (tested to be) undefined.  If this is any help, the files
> that don't pass the (-e $_) of test of line 11 are (perhaps coincidentally)
> the biggest files (~55 GB)  in the directory.
> 
> I've researched the File::Find documentation and checked the FAQ's with no
> luck, so I'm hoping someone out there can help me.
> 
> Also, is there a function that returns a minimum value in an array?  It's
> not my biggest concern right now, but it would make line 20 simpler.
> 
>  1: #!/usr/local/bin/perl -w
>  2:
>  3: use Cwd;
>  4: use File::Find;
>  5: use FileHandle;
>  6:
>  7: ($filecount = shift) || ($filecount = 20);
>  8:
>  9: sub wanted{
> 10:  my $flag = 0;
> 11:  if (-e $_){
> 12:   push(@filelist, [$File::Find::name, -s $_, -M $_]);
> 13:    }
> 14:  }
> 15:
> 16: $dir = cwd();
> 17:
> 18: find(\&wanted,$dir);
> 19:
> 20: foreach $fileref ((sort {$b->[1] <=> $a->[1]} @filelist)[0..(sort( {$a
> <=>$b} $filecount,scalar(@filelist)-1))[0]]){
> 21:  write STDOUT;
> 22:  }
> 23:
> 24: STDOUT -> format_name("STDOUT_BOT");
> 25: write STDOUT;
> 26:
> 27: format STDOUT_TOP=
> 28: FILENAME
> FILE SIZE (BYTES)  AGE (DAYS)
> 29:
> 
>------------------------------------------------------------------------------------------------------------------
> 30: .
> 31: format STDOUT=
> 32:
> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> 
> >>>>>>>>>>>>>>>>    @>>>
> 33: $fileref->[0], $fileref->[1], sprintf("%4.0f", ($fileref->[2]))
> 34: .
> 35: format STDOUT_BOT=
> 36:
> 
>-----------------------------------------------------------------------------------------------------------------
> 37: .
> .


Here is something that I think does what you want:

#!/usr/local/bin/perl -w
use strict;
use Cwd;
use File::Find;
use FileHandle;

my $filecount = shift || 20;
my @filelist;
our $fileref;

# This stores _at most_ $filecount entries in @filelist so sorting is
fast
# and you don't have to store _all_ file names.  Also int(-M $_) since
you
# are only reporting the age in days.  Files are stored with the largest
# file at the top of the array @filelist (largest, second largest, third
# largest, ... $filecount largest)
sub wanted {
    @filelist = sort { $b->[1] <=> $a->[1] } ( @filelist, [
$File::Find::name, -s $_, int(-M $_) ] );
    pop @filelist if @filelist > $filecount;
    }

my $dir = cwd();

find( \&wanted, $dir );

for $fileref ( @filelist ) {
    write STDOUT;
    }

STDOUT->format_name("STDOUT_BOT");
write STDOUT;

# the rest of the program is unchanged from original



John
-- 
use Perl;
program
fulfillment

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to