in reply to aborting File::Find::find

Perhaps the easiest way is to die, and wrap the find call with eval.

eval { find( sub { ...; --$fnlinks or die; }, $dir ); };

Update: Another goto-like solution, if you don't like the idea of generating an exception:

UNLINKS: { find( sub { ...; --$fnlinks or last UNLINKS; }, $dir ); }

We're building the house of the future together.

Replies are listed 'Best First'.
Re^2: aborting File::Find::find
by Limbic~Region (Chancellor) on Nov 16, 2006 at 18:42 UTC
    jdporter,
    If you want scary action at a distance that is subject to break if the implementation changes:
    find(sub { ...; --$fnlinks or last Proc_Top_Item; }, $dir);
    I found this by looking under the File::Find covers.

    Now that I think about it, this sounds like the sanest solution. Of course I mean a patch to File::Find where you can either set some flag or pass in a closure that evaluates to true to determine if it can terminate early which is checked each loop.

    Cheers - L~R

Re^2: aborting File::Find::find
by Fletch (Bishop) on Nov 16, 2006 at 18:27 UTC

    You probably would want to die with a specific string (maybe "FOUND_ALL_LINKS") and check $@ after the eval to make sure that you really exited because you hit your link limit rather than something else going wrong and dieing.

Re^2: aborting File::Find::find
by marvell (Pilgrim) on Nov 16, 2006 at 18:16 UTC
    It's certainly more efficient, but not exactly Mr Elegant. Nor is a goto. However, it is still top of the lsit of solutions. Thanks.

    --
    Steve Marvell

      One way to make the eval/die a little more elegant is to use the Error module and have 'real' exceptions:
      #!/usr/bin/perl use warnings; use strict; use Error qw/:try/; use File::Find; { package Exception::FoundFile; use base qw/Error/; sub new { my $s = bless {}, __PACKAGE__; $s->{_file} = shift; return $s; } sub file { return shift->{_file}; } } try { find(sub { my $file = $File::Find::name; # Show our working, so you can see we stop early print "Examining $file\n"; throw Exception::FoundFile->new($file) if ($file =~ /f/); # Or whatever your condition is }, "."); } catch Exception::FoundFile with { my $e = shift; print "Found file: ", $e->file, "\n"; } otherwise { print "Didn't find a file\n"; };
      But the 'real solution' would be for the File::Find interface to respect a return value from the sub as to whether it should continue or not.

      Too late for that now, sadly.