oryann9 wrote:
Randal L. Schwartz - Stonehenge Consulting Services, Inc.
You're misusing it. Set it within the wanted() routine when you're
looking at a directory that you don't want to descend. It'll be
cleared to 0 before calling wanted(), so setting it before calling
find() is completely useless.
Will anyone help me with this issue? These three lines of code work,
but work in a way that I am not expecting. When I tell this module to
set no_chdir to 1 it should NOT descend directories yet it does.
no_chdir does not do what you seem to think it does. No matter what the
value of no_chdir is File::Find::find will *always* descend directories.
perldoc File::Find
[ SNIP ]
"no_chdir"
Does not "chdir()" to each directory as it recurses.
Note that it still recurses, it just does not chdir().
You want to set the $File::Find::prune variable to true from *inside*
File::Find::find's wanted subroutine. But of course you can't do that
with File::Find::Closures unless you define your own closure.
Am I supposed to have a wanted routine other than whats below? Below
are the 3 lines I have tried and below that is the entire script.
thank you!
1) File::Find::find ( { wanted => $wanted, no_chdir => $File::Find::no_chdir },
$fs ) ;
2) File::Find::find ( { wanted => $wanted, no_chdir => +shift }, $fs ) ;
3) File::Find::find ( { wanted => $wanted, no_chdir => $File::Find::no_chdir =
shift}, $fs
#!/usr/bin/perl
use strict ;
use warnings ;
use File::Find ;
use File::Find::Closures qw(find_by_min_size) ;
##-- Begin Format Code --##
my ($key,$user,$grp,$mod,$sz) ;
format STDOUT_TOP =
Page @<<<
$%
FileName
Owner GroupOwner LastMo
ate Size
=========
======= =========== ======
==== =====
.
format STDOUT =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<< @<<<<<<
@<<<<<
<<< @##.###
$key,
$user, $grp, date_m
That should be $mod instead of 'date_m'.
, $sz
.
##-- End Format Code --##
sub date_me {
my $mod = shift @_ ;
my ($seconds, $minutes, $hours, $day_of_month, $month, $year,
undef, undef, undef) = localtime($mod) ;
#printf("%02d:%02d:%02d-%02d/%02d/%04d",
( $hours, $minutes, $seconds, $month+1, $day_of_month, $year+1900 ) ;
}
my $log = qq(/var/adm/find_hog.log) ;
my $logg ;
open ($logg, '>>', $log) or warn "file '$logg' was not opened $!" ;
You are just using warn() which means that you want to print to $log
whether the file was opened or not?
START:
print qq (\nPlease enter filesystem name in the form of /fsname or / just for
root\n) ;
print "\n";
chomp (my $fs = <>) ;
if ( $fs eq "/" ) { # only if the root directory, do not descend.
find_me ( $fs, 0 );
}
elsif ( $fs =~ m|^/\w+|i ) { ## matches /var
find_me ( $fs, 1 );
}
elsif ( $fs =~ m|^[/.\w+]|i ) { ## matches /.ssh
That pattern will never match '/.ssh'. It will match a single character
at the beginning of the line, one of either '/', '.', '+' or a member of
the character class \w. If you want it to match /.ssh then try m|^/\.\w+|.
Or better yet, combine the two previous:
elsif ( $fs =~ m|^/\.?\w+|i ) {
find_me ( $fs, 1 );
}
else {
warn "\nFilesystem name does not match expression.\nPlease contact Unix on
call and or try again\n
goto START;
}
It is poor form to use goto:
START: {
print "\nPlease enter filesystem name in the form of /fsname or /
just for root\n\n";
chomp( my $fs = <> );
if ( $fs eq '/' ) { # only if the root directory, do not descend.
find_me( $fs, 0 );
}
elsif ( $fs =~ m|^/\.?\w+| ) { ## matches /var or /.ssh
find_me( $fs, 1 );
}
else {
warn "\nFilesystem name does not match expression.\nPlease
contact Unix on call and or try again\n";
redo START;
}
}
my ( @sorted_large_files, @large_files ) ;
sub find_me {
use Data::Dumper;
my $fs = shift;
#local $File::Find::prune = shift; ##-- localize prune to just this block
--##
#my @directory = ($fs) ;
use constant MAX_SIZE => (25*1024*1024) ;
use constant DIVISOR => (1024) ;
my ( $wanted, $list ) = find_by_min_size ( MAX_SIZE ) ;
File::Find::find ( { wanted => $wanted, no_chdir => +shift }, $fs ) ;
@large_files = $list->() ;
@sorted_large_files =
sort { -s $b <=> -s $a }
@large_files ;
You are stat()ing the files more than you need to. You can use a
Schwartzian Transform to minimize IO:
@sorted_large_files =
map $_->[ 0 ],
sort { $b->[ 1 ] <=> $a->[ 1 ] }
map [ $_, -s ],
$list->();
} ##-- End sub --##
if (@sorted_large_files) {
You don't need this section of code inside an if block:
unless ( @sorted_large_files ) {
warn "\nNo file(s) over twenty-five Mb found in $fs\n";
exit 0;
}
my %meta ;
for my $file (@sorted_large_files) {
$meta{$file} = {
'uid' => (stat($file))[4],
'gid' => (stat($file))[5],
'sz' => (stat($file))[7],
'mod' => (stat($file))[9],
} ;
You can simplify that (and only call stat() once) with a hash slice:
my %meta;
for my $file ( @sorted_large_files ) {
@{ $meta{ $file } }{ qw/uid gid sz mod/ } = ( stat $file )[ 4, 5,
7, 9 ];
}
} ## END FOR ##
for $key ( keys %meta ) {
$user = getpwuid $meta{$key}->{'uid'} ;
$grp = getgrgid $meta{$key}->{'gid'} ;
$mod = $meta{$key}{'mod'} ;
$sz = $meta{$key}{'sz'} / DIVISOR / DIVISOR ;
#print "\n$key => $user\t$grp\t\t" ;
#date_me($mod) ;
#printf("\t%0.3f Mb\n",$sz) ;
write ;
}
} ##-- End @sorted_large_files if --##
else {
warn "\nNo file(s) over twenty-five Mb found in $fs\n" ;
exit 0 ;
}
END {
close ($logg) or warn "Log '$logg' failed to close $!" ;
}
An END{} block will execute at the end of the program no matter where it
is physically placed in the file so why not put it closer to where the
file is opened.
John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/