views:

159

answers:

3

I have code like below. If I open the file $File::Find::name (in this case it is ./tmp/tmp.h) in my search function (called by File::Find::find), it says "cannot open the file ./tmp/tmp.h reason = No such file or directory at temp.pl line 36, line 98."

If I open the file directly in another fuction function, I am able open the file. Can somebody tell me the reason for this behavior? I am using activeperl on Windows and the version is 5.6.1.

use warnings;
use strict;
use File::Find;

sub search
{
    return unless($File::Find::name =~ /\.h\s*$/);
    open (FH,"<", "$File::Find::name") or die "cannot open the file $File::Find::name  reason = $!";
    print "open success $File::Find::name\n";
    close FH;

}

sub fun
{
    open (FH,"<", "./tmp/tmp.h") or die "cannot open the file ./tmp/tmp.h  reason = $!";
    print "open success ./tmp/tmp.h\n";
    close FH;

}

find(\&search,".") ;
A: 

If ./tmp/ is a symbolic link then you will need to do following:

find( { wanted => \&search, follow => 1 }, '.' );

Does that help?

/I3az/

draegtun
He is on Windows. I doubt this has to do with symlinks.
Sinan Ünür
Does open() work with forward slashes on Windows then? Re: symlinks - What about mounted UNIX/Linux share... will symlinks automatically be followed from Windows?
draegtun
@draegtun Yes, `open` does work with forward slashes. `"tmp/tmp.h"` is preferred to `"tmp\\tmp.h"` (I prefer `File::Spec::catfile`). I do not know the answer to your second question.
Sinan Ünür
@Sinan: Thanks for info. Its been nearly 10 years since I've used Perl on Windows!! re: File::Spec... yes nice but I'll raise u Path::Class ;-)
draegtun
@draegtun `Path::Class` wins! *how many people actually take the "volume" (like C: on Windows) into account when writing File::Spec-using code? I thought not.*
Sinan Ünür
+10  A: 

See perldoc File::Find: The wanted function (search in your case) will be called after File::Find::find changed to the directory that is currently searched. As you can see, $File::Find::name contains the path to the file relative to where the search started. That path that won't work after the current directory changes.

You have two options:

  1. Tell File::Find to not change to the directories it searches: find( { wanted => \%search, no_chdir => 1 }, '.' );
  2. Or don't use $File::Find::name, but $_ instead.
innaM
A: 

If you want to search the file in current working dir you can use Cwd.

use warnings;
use strict;
use File::Find;
use Cwd;

my $dir = getcwd;

sub search
{
    return unless($File::Find::name =~ /\.h\s*$/);
    open (FH,"<", "$File::Find::name") or die "cannot open the file $File::Find::name  reason = $!";
    print "open success $File::Find::name\n";
    close FH;

}

find(\&search,"$dir") ;
Space
This might actually work because getcwd will return an absolute path. But your answer sure requires a bit more explaining.
innaM