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

Hi

Well when I first ran into this problem I thought that it would be a simple problem to solve. but I can't seem to figure it out. The problem occurs when I am using File::Find to recusivly search a direcotry for files. The problem is that when i get to a directory that doesn't exist it prints out.

Can't stat e:\logs: No such file or directory

I have to search many directories and if the program doesn't find one it just spits out this message and goes on to the next one. Well I want to be able to know if it couldn't not find that direcotry.

Well at first i tried setting a variable equal to tbe return value.

my $temp =  find ({wanted =>  \&wanted,bydepth =>0},"e:\\logs",);

But the problem was that even if it worked or if it didn't find the directory it would return zero. So next I tried to eval the statement and to catch the error that way.

eval{ find ({wanted => \&wanted,bydepth =>0},"e:\\logs",) }; warn $@ if $@;
But it didn't catch the error

I know that there is a module out there called "exceptions" to use try and catch but I installed it and it tells me i need to install "methodmaker". And I don't even know if exceptions will work. I know that there is also something that is called "backticks" that is used to get what is outputed to the screen (i think). Is there a simple way to figure out if it returned an error or not??

any help would be great thanks,

Victor

Replies are listed 'Best First'.
Re: catching errors from file::find
by Fastolfe (Vicar) on Nov 09, 2001 at 01:51 UTC

    You might want to consider re-working your logic.

    @to_search = qw' /exists /doesnt-exist '; # master list find( { wanted => \&wanted, bydepth => 0 }, grep { -d } @to_search);

    If you REALLY need to know which ones don't exist, consider grepping that out beforehand.

    @not_found = grep { ! -d } @to_search; warn "Not found: " . join(", ", @not_found) . "\n" if @not_found;
(jeffa) Re: catching errors from file::find
by jeffa (Bishop) on Nov 09, 2001 at 02:01 UTC
    Before you even call find(), add this:
    # assuming you don't mind shifting off the first arg my $start = shift || 'e:\logs'; warn "$start doesn't exist" unless -e $start; # or whatever you want to do with the 'exception'
    The only time find() will die like that is if it can't even stat it's second argument - inside the recursive magic, it only stats what it finds. Otherwise, do what Fastolfe suggested.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    F--F--F--F--F--F--F--F--
    (the triplet paradiddle)
    
Re: catching errors from file::find
by belg4mit (Prior) on Nov 09, 2001 at 01:52 UTC
    You ought to checkout %SIG in perlman:perlvar, specfiically __WARN__ so something like the following before your find:
    $SIG{__WARN__} = sub{ print "There is no: $_[0]\n"; }
    Doing whatever it is sepcifically you need to do to notify yourself about non-existant directories.

    UPDATE: Based on jeffa's response I may have misinterepreted what you want, and this is overkill...

Re: catching errors from file::find
by tachyon (Chancellor) on Nov 09, 2001 at 06:17 UTC

    If you are not averse to rolling your own then this may do the trick:

    #!/usr/bin/perl -w use strict; my $root = 'c:/cluster1/'; # must have trailing path delim! my $delim = '/'; my @dirs = ($root); my @files; for my $path (@dirs){ opendir ( DIR, $path ) or next; # skip dirs we can't read while (my $file = readdir DIR) { # skip the dot files next if $file eq '.' or $file eq '..'; # skip symbolic links next if -l $path.$file; if ( -d $path.$file ) { # add the dir to our dir list push @dirs, $path.$file.$delim; } else { # add the file to file list push @files, $path.$file; } } closedir DIR; } print "Directory list\n\n"; print "$_\n" for sort @dirs; print "\n\nFile List\n\n"; print "$_\n" for sort @files;

    This works by adding found directories to the end of the @dirs list we are iterating over. BTW I don't quite understand how you get to a directory that does not exist but you can change the default behaviour of this code when it can't opendir a DIR to whatever you want. Just change the next.....

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: catching errors from file::find
by gloryhack (Deacon) on Nov 10, 2001 at 00:03 UTC
    my $directory = 'e:\logs'; my $temp = -d $directory ? find ({wanted => \&wanted,bydepth =>0}, $di +rectory) : undef;
    Or, maybe:
    if (-d $directory) { # find... } else { # do some error processing stuff }
Pathing under Windows
by petdance (Parson) on Nov 10, 2001 at 09:24 UTC
    Please consider not using backslashes as path separators. Perl doesn't care if you're in Windows or Unix: You can use / as a path separator.

    "c:/config.sys" is the same as "c:\\config.sys" and 'c:\config.sys', but not prone to the quoting goofs.

    xoxo,
    Andy
    --
    <megaphone> Throw down the gun and tiara and come out of the float! </megaphone>

      As long as we're wandering down this path... it's also good to get into the habit of using single quotes unless variable interpolation is required. Lots of sneaky little bugs hide inside double quotes.

      (In my message previous, I went with the bugslash because the point I was making was how to solve the original problem, rather than correcting style.)

      While this is certainly true in the latest version of ActivePerl for Windows, there was a time when the double backslash was the only safe way to proceed.... I can't remember what version it was that life became easier for us windozers, and I no longer have an older install to test it. Anyone with better memory than me want to chime in here?