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]