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


Hi there

I have a problem. When I try to open files found by File::Find they are not recongnized as files if they are located in a sub directory, and if the directory is pointed out as a relative path. Here is some code; I also post my test code so you can see what kind of tests I have made
use File::Find; use Getopt::Std; sub process_file { my $file_short=$_; my $file = $File::Find::name; return if ($file_short eq "test.pl"); print "file name $file_short\n"; print "long filename $file\n"; if (-f $file && -r $file) { open (INPUT, "<", "$file") or die "unable to open file $file bec +ause: $!"; } while ($line=<INPUT>){ print "$line \n"; } ### end of worki if (-f $file) { open (OUTPUT, ">c:\\temp\\merck_out\\$file_short.out") || die (" +Unable to openc:\\merck_out\\$file_short.out for writing exiting...") +; } } getopts('d:'); my $dir = $opt_d; print " dir $opt_d\n"; find(\&process_file, $opt_d); ### this one is working #open (INPUT2, '<./test_folder/forecast_debug.txt') || die ("Unable to + open .\merck_test\forecast_debug.txt for input reson $!"); #while ($line=<INPUT2>){ # print "$line \n"; #} ### end of working ### this one is working #open (INPUT2, '<.\merck_test\forecast_debug.txt') || die ("Unable to +open .\merck_test\forecast_debug.txt for input reson $!"); #while ($line=<INPUT2>){ # print "$line \n"; #} ### end of working ### this one is working as well #my $strFile2 = '.\merck_test\forecast_debug.txt'; #open (INPUT3, "<$strFile2") || die ("Unable to open $strFile2_debug.t +xt for input reson $!"); #while ($line=<INPUT3>){ # print "$line \n"; #} ### end of working ### works as well #my $strFile3 = "./merck_test/forecast_debug.txt"; #open (INPUT3, "<$strFile3") || die ("Unable to open $strFile3 for inp +ut reson $!"); #while ($line=<INPUT3>){ # print "$line \n"; #} ### end of working close INPUT; close OUTPUT; close INPUT2; close INPUT3
So... If I start this, in dir c:\temp with:
test.pl -d .
it will find all files under the current dir, but it can not open any file in a sub dir.
But... If I give an absolute path and start it like this:
test.pl -d 'C:\temp'
it will work, and will be able to open the files in the sub folder.
does any one have an idea or solution for this, because I really want to use relative path's in my function
Best regars

Pär

Replies are listed 'Best First'.
Re: unable to open files in dirs retrived by File::Find
by almut (Canon) on May 27, 2008 at 09:28 UTC

    You need to use the option no_chdir, otherwise File::Find will chdir into the subdirectories it recurses into, so the relative path no longer applies...

    find({ wanted => \&process_file, no_chdir => 1 }, '.');
      Thank you very much for the help everybody. Now it works fine
Re: unable to open files in dirs retrived by File::Find
by ikegami (Patriarch) on May 27, 2008 at 09:29 UTC

    Quote the docs:

    Additionally, for each directory found, it will chdir() into that directory and continue the search, invoking the &wanted function on each file or subdirectory in the directory.

    You need to use $file_short instead of $file, or you need to specify no_chdir => 1 in the options you pass to find/finddepth. Or you could use File::Find::Rule.

Re: unable to open files in dirs retrived by File::Find
by zentara (Cardinal) on May 27, 2008 at 11:37 UTC
    Update. Corion pointed out that $File::Find::name is nothing more than $File::Find::dir/$_..... oops. Maybe the second example will shed some light, but I don't use win32 so there may be slash issues. Sorry it's a groggy morning. :-)

    Sometimes its useful to use $File::Find::dir

    #!/usr/bin/perl #finds files older than 30 days use warnings; use strict; use File::Find; my $top = shift || "."; find sub {return unless -f; if (-M _ > 30){print "$File::Find::dir/$_\n"} }, "$top";

    #!/usr/bin/perl #finds files older than 30 days use warnings; use strict; use File::Find; my $top = shift || "."; find sub {return unless -f; if (-M _ > 30){ my $dirpath = File::Spec->rel2abs( '.' ); print "$dirpath\n"; print "$File::Find::dir/$_\n"; print "$File::Find::name\n"; print "$dirpath\/$_\n\n"; } }, "$top";

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum