mikejones has asked for the wisdom of the Perl Monks concerning the following question:

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 set prune to 0 it should NOT descend directories yet it does. Below are the 3 lines I have tried and below that is the entire script. thank you!

1) File::Find::find ( { wanted => $wanted, prune => $File::Find::prune + }, $fs ) ; 2) File::Find::find ( { wanted => $wanted, prune => +shift }, $fs ) ; 3) File::Find::find ( { wanted => $wanted, prune => $File::Find::prune = 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 , $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+1 +900 ) ; } my $log = qq(/var/adm/find_hog.log) ; my $logg ; open ($logg, '>>', $log) or warn "file '$logg' was not opened $!" ; START: print qq (\nPlease enter filesystem name in the form of /fsname or / j +ust 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 find_me ( $fs, 1 ); } else { warn "\nFilesystem name does not match expression.\nPlease contac +t Unix on call and or try again\n goto 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 thi +s 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, prune => $File::Find::prun +e }, $fs ) ; @large_files = $list->() ; @sorted_large_files = sort { -s $b <=> -s $a } @large_files ; } ##-- End sub --## if (@sorted_large_files) { 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], } ; } ## 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 $!" ; }

Replies are listed 'Best First'.
Re: File::Find::prune saga (way off)
by tye (Sage) on Jan 16, 2008 at 16:35 UTC
    When I tell this module set prune to 0 it should NOT descend directories

    I don't know where you got that idea.

    First, there is no 'prune' option that you can pass in to File::Find::find(). Second, you have to set $File::Find::prune to one (not zero). Third, you have to set it from within your "wanted" subroutine when the traversal gets to a directory that you don't want the traversal to descend into.

    In your case, you appear to want to have your "wanted" subroutine always set $File::Find::prune= 1; so no subdirectories are traversed into.

    - tye        

      hello monks, I am getting the error at the first write statement:  Undefined format "STDOUT" Any ideas and help would be much appreciated! I posted this on Perl beginners as well.

      #!/usr/bin/perl use strict ; use warnings ; use File::Find ; use File::Find::Closures qw(find_by_min_size) ; $ENV{"PATH"} = qq(/usr/bin:/bin) ; delete @ENV{qw (IFS CDPATH KSH_ENV)} ; my ( $key, $keys, $user, $grp, $gcos, $mod, $mod2, $sz, ) ; my ( @sorted_large_files, @sorted_root_files, ); <snip> sub dateme { ##-- $mod is for modification time from file(s) --## my $mod = shift @_ ; my ($seconds, $minutes, $hours, $day_of_month, $month, $year, undef, undef, undef ) = localtime( $mod ) ; ##-- $mod2 is like $mod, but does more, allows user to see mod tim +e from sprintf --## my $mod2 = sprintf( "%02d:%02d:%02d-%02d/%02d/%02d", ( $hours, $minutes, $seconds, $month + 1, $day_of_month, ( $year % 100 ) ) ) ; } <snip> ##-- Begin Main --## #===================# print qq(\n) ; my $fs = $ARGV[0] ; my $size = ( $ARGV[1] * 1024 * 1024 ) ; $fs =~ tr /\000//d ; ##-- Clean user input --## $size =~ tr /\000//d ; die qq ( \nPlease enter filesystem followed by minimum file size to se +arch. Usage example: find_hog /var 25 will look in /var for files >= 25Mb\n\ +n ), unless ( $fs and $size ) ; my ( @root_files, @large_files, ) ; if ( $fs eq "/" ) { ## only if the root directory <snip> } elsif ( $fs =~ m|^/\w+|i ) { ## matches /var find_me( $fs, $size, 0 ) ; } elsif ( $fs =~ m|^[/.\w+]|i ) { ## matches /.ssh find_me( $fs, $size, 0 ) ; } sub find_me { my $fs = shift @_ ; my $size = shift @_ ; my ( $wanted, $list ) = find_by_min_size( $size ) ; File::Find::find( { wanted => $wanted, no_chdir => +shift }, $fs ) + ; @large_files = $list->() ; } ##-- End sub --## ##-- Gather meta-data --## #=========================# use constant DIVISOR => ( 1024 ) ; use constant LINES_PER_PAGE => ( 44 ) ; if ( @large_files ) { my %meta ; for my $file ( @large_files ) { $meta{$file} = { 'uid' => ( stat( $file ) )[4], 'gid' => ( stat( $file ) )[5], 'sz' => ( stat( $file ) )[7], 'mod' => ( stat( $file ) )[9], } ; } ##-- End For --## for $key ( keys %meta ) { $user = qq(N/A) unless $user = (getpwuid ( $meta{$key}->{'uid'} ) )[0] ; +##-- uid name --## $grp = qq(N/A) unless $grp = (getgrgid ( $meta{$key}->{'gid'} ) )[0] ; +##-- gid name --## $gcos = qq(N/A) unless $gcos = (getpwuid ( $meta{$key}->{'uid'} ) )[6] ; # +#-- gcos --## $mod = qq(N/A) unless $mod = $meta{$key}{'mod'} ; $sz = qq(N/A) unless $sz = $meta{$key}{'sz'} / DIVISOR / DIVISOR ; my $ofh = select( STDOUT ) ; $= = LINES_PER_PAGE ; select( $ofh ) ; write ; ## THIS IS WHERE THE ERROR IS ## $ofh = select( LOG ) ; $= = LINES_PER_PAGE ; select( $ofh ) ; write( $ofh ) ; } ##-- End For --## ##-- Sort values according to sz --## @sorted_large_files = sort { $meta{$b}->{'sz'} <=> $meta{$a}->{'sz'} } keys %met +a; } ##-- End @large_files if --## <snip> ##-- Begin Format Code --## #==========================# $^L = q{}; format STDOUT_TOP = REPORT OF LARGE FILES on: @<<<<<<<<<< qx(hostname) Page @<<< $% FileName + Owner GroupOwner Gecos LastModifiedD +ate Size Mb ========================= + ======= =========== ====== ============= +==== ======= . format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<< @<<<<<<< @<<<<<< @<<<<<<<<<<<<<<<<<<<<<<< @||||||||||||| + @##.## @sorted_large_files, + dateme($mod, +$mod2) . <snip> ##-- End Format Code --## #========================# else { warn "\nNo file(s) over $size Mb found in $fs\n" ; exit 0 ; } #print "\n"; #print join("\n",@sorted_large_files); #print join("\n",@sorted_root_files); END { close( LOG ) or warn "Log '$log' failed to close $!" ; }
Re: File::Find::prune saga
by runrig (Abbot) on Jan 16, 2008 at 22:39 UTC
    If you don't want to descend into any directories, then you are likely better off with opendir/readdir/closedir or glob. If you don't want to descend into certain directories, then you set $File::Find::prune to 1 inside your wanted subroutine when the current directory is one you do not want to descend into.
Re: File::Find::prune saga
by merlyn (Sage) on Jan 17, 2008 at 16:38 UTC