On Jan 17, 2008 3:52 PM, oryann9 <[EMAIL PROTECTED]> wrote:
snip
> 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. 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.
snip

No one can help you with the issue because you are asking for 1 + 1 to equal
3.  The no_chdir option will not do what you want; it can't because it
doesn't control the recursion of File::Find::find.

from perldoc File::Find
      "no_chdir"
         Does not "chdir()" to each directory as it recurses. The "wanted()"
         function will need to be aware of this, of course. In this case, $_
         will be the same as $File::Find::name.
snip
      You are chdir()'d to$File::Find::dir when the function is called,
      unless "no_chdir" was specified. Note that when changing to
directories
      is in effect the root directory (/) is a somewhat special case
inasmuch
      as the concatenation of $File::Find::dir, '/' and $_ is not literally
      equal to $File::Find::name. The table below summarizes all variants:

                    $File::Find::name  $File::Find::dir  $_
       default      /                  /                 .
       no_chdir=>0  /etc               /                 etc
                    /etc/x             /etc              x

       no_chdir=>1  /                  /                 /
                    /etc               /                 /etc
                    /etc/x             /etc              /etc/x

This means that File::Find::find will still recurse into each subdirectory,
but it will not set the current working directory for the program to those
directories inside the wanted function and it will modify the
$File::Find::name, $File::Find::dir, and $_ in a different manner.

If you want to avoid recursing into a directory then you need to set
$File::Find::prune
inside the function you are passing to File::Find::find, unfortunately, you
are using File::Find::Closures to create the function you are passing to
File::Find::find (instead of writing it yourself) and therefore you cannot
set $File::Find::prune inside of it.  Therefore, you need to wrap the
function returned by find_by_min_size with another function that sets
$File::Find::prune
when you want it set:

#!/usr/bin/perl

use strict;
use warnings;

#these should be declared near the top
use constant MAX_SIZE => 10*1024*1024; #ten meg
use constant DIVISOR  => 1024;

use File::Find;
use File::Find::Closures qw(find_by_min_size);

sub find_me {
    my ($fs, $do_not_recurse) = @_;
    my ($wanted, $list) = find_by_min_size(MAX_SIZE);
    File::Find::find (
        {
            wanted => sub {
                #if $do_not_recurse is true and we are in a
                #directory other than the one we are searching
                #then set $File::Find::prune so File::Find::find
                #will know not to recurse
                $File::Find::prune =
                    $do_not_recurse && $File::Find::name ne $fs;
                #call the function that will normally would
                #have been passed to File::Find::find
                $wanted->();
            }
        },
        $fs
    );
    return sort { -s $b <=> -s $a } @{$list->()};
}

#this one doesn't recurse
print "large files in /:\n", map { "$_\n" } find_me("/", 1);
#both of these will
print "large files in /var:\n", map { "$_\n" } find_me("/var", 0);
print "large files in /tmp:\n", map { "$_\n" } find_me("/tmp");

Reply via email to