File::Find problem?

M

Monty

I'm using the File::Find module to search through a directory tree and
perform operations on files with a .hdr suffix for the file name. I
have a test environment set up and known defects in the files, but I
get an error I hadn't expected with the find() function. The set up
is like this:

use File::Find;

find (\&process_file,".");

sub process_file {
if (/\.hdr/) {
print "$File::Find::name\n";
open HDR_FILE, "<$File::Find::name" or die "Can't open file
for input: $!\n";
...etc.

It prints the correct file name, complete with relative path, but it
dies on the open statement every time. What am I doing wrong?

Thanks in advance.
 
J

J. Gleixner

Monty said:
I'm using the File::Find module to search through a directory tree and
perform operations on files with a .hdr suffix for the file name. I
have a test environment set up and known defects in the files, but I
get an error I hadn't expected with the find() function. The set up
is like this:

use File::Find;

find (\&process_file,".");

sub process_file {
if (/\.hdr/) {

Note: this only means that '.hdr' occurs in the name of the file. It
would match some.file.hdr.gif too.
print "$File::Find::name\n";

print " is readable\n" if -r $File::Find::name;
print " does exist\n" if -e $File::Find::name;
open HDR_FILE, "<$File::Find::name" or die "Can't open file
for input: $!\n";
...etc.

It prints the correct file name, complete with relative path, but it
dies on the open statement every time. What am I doing wrong?

Well, what's the error?
What's a value of $File::Find::name?
Do you have read access to the file?
Is it a symlink to a file that doesn't exist?
 
M

Monty

Ah, I left a few things out.

The error is as in the die statement: Can't open file for input. All
files in the test environment have permissions of 777 (that includes
the directories and sub-directories), so anyone should be able to
read, write, or execute them (although they're plain text files). On
top of that, I'm running this as root.

Also, I mistyped the 'if' statement some, it actually reads 'if (/\.hdr
$/)'. That part seems to work just fine.

I'm stumped, but thanks for taking a look at this.

Monty
 
R

Ron Bergin

Ah, I left a few things out.

The error is as in the die statement: Can't open file for input. All

What's the second half of the error message i.e., what's the value of
$! (the OS portion of the error)?
 
M

Monty

The O/S portion of the error is "No such file or directory".

The file exists where $File::Find::name says it is. I wonder if the
problem is in the relative pathing?
 
H

Henry Law

Monty said:
Oh yes, none of these files are symbolic links.

Please post your real code (don't re-type it), together with the output
you get when you run that very code.

This, for example, is based on your code and works on my Win XP machine.
(I've replaced your "hdr" extension with "doc" for convenience).

#! /usr/bin/perl
use strict;
use warnings;
use File::Find;

find (\&process_file,".");

sub process_file {
if (/\.doc$/) {
print "$File::Find::name ...";
print "exists, " if -e $File::Find::name;
print "is readable, " if -r $File::Find::name;
open HDR_FILE, "<$File::Find::name" or die "Can't open file for
input: $!\n";
print "opened OK\n";
close HDR_FILE;
}
}

Output:
F:\WIP>clpm.pl
../IAM Capability Strategy V1.11.doc ...exists, is readable, opened OK
../Annual General Meeting 07.doc ...exists, is readable, opened OK
and so on.
 
H

Henry Law

Henry said:
Output:
F:\WIP>clpm.pl
../IAM Capability Strategy V1.11.doc ...exists, is readable, opened OK
../Annual General Meeting 07.doc ...exists, is readable, opened OK
and so on.

For some reason Thunderbird has put two dots where my original output
has one. The console shows one dot (the current directory).
../IAM Capability Strategy V1.11.doc ...exists, is readable, opened OK
../Annual General Meeting 07.doc ...exists, is readable, opened OK

(Unless TBird munges it again!)
 
U

usenet

I'll bet it is.

Are you running the program from the same root path that the find is
looking at? Do you chdir() either to or away from that root path in
your program?
 
R

Ron Bergin

Are there spaces in the filename and/or path?

Since the default is to cd into each dir, you should be able ti use $_
instead of $File::Find::name
Try changing the open call to this:

open(HDR_FILE, '<', "$_") || die "Can't open file or input: $!";
 
T

Tad McClellan

Ron Bergin said:
Try changing the open call to this:

open(HDR_FILE, '<', "$_") || die "Can't open file or input: $!";


perldoc -q vars

What’s wrong with always quoting "$vars"?

then try instead:

open(HDR_FILE, '<', $_) || die "Can't open file or input: $!";
 
R

Ron Bergin

perldoc -q vars

What's wrong with always quoting "$vars"?

then try instead:

open(HDR_FILE, '<', $_) || die "Can't open file or input: $!";

Tad,

I'm aware of the reasons for not always quoting "$vars" and I rarely
do quote them, however, I did in this case to safeguard against the
possibility of having spaces in the filename, in which case the open
call would fail if it was not quoted. I know that spaces in filenames
aren't real common on *nix systems, but on occasion it does happen and
on Windows systems it's very common.

I probably should have been more clear as to my reasoning when I
posted that suggestion. Additionally, we both left out one important
piece...we should have included $_ or $File::Find::name within the die
statement.
 
R

Ron Bergin

Tad,

I'm aware of the reasons for not always quoting "$vars" and I rarely
do quote them, however, I did in this case to safeguard against the
possibility of having spaces in the filename, in which case the open
call would fail if it was not quoted.

Hmmm It looks like I need to correct myself. I just ran a test on my
*nix box without quoting the var and it did open a file with spaces in
the name. I know that I've had problems in the past with spaces in
the names, but that may have been on older version of Perl on Windows.
 
U

Uri Guttman

RB> Hmmm It looks like I need to correct myself. I just ran a test on my
RB> *nix box without quoting the var and it did open a file with spaces in
RB> the name. I know that I've had problems in the past with spaces in
RB> the names, but that may have been on older version of Perl on Windows.

spaces in file names are allowed under almost all filesystems. most any
programming language api for open can handle spaces just fine. you are
probably thinking about quoting those names when used in the shell. but
when you shell out you need to use quotes at the shell level but inside
a string in the perl code and then it can be confusing.

uri
 
J

John W. Krahn

Monty said:
The O/S portion of the error is "No such file or directory".

The file exists where $File::Find::name says it is. I wonder if the
problem is in the relative pathing?

That is exactly the problem. $File::Find::name contains the complete path of
the file. The problem is that File::Find::find defaults to changing
directories so that the file in question is always in the current directory.
So if $File::Find::name contains './one/two/three/file.txt' you are trying to
open a file in './one/two/three/./one/two/three/file.txt'. You need to either
use the "no_chdir" option or use just the file name in $_.


John
 
R

Randal L. Schwartz

Monty> I'm using the File::Find module to search through a directory tree and
Monty> perform operations on files with a .hdr suffix for the file name. I
Monty> have a test environment set up and known defects in the files, but I
Monty> get an error I hadn't expected with the find() function. The set up
Monty> is like this:

Monty> use File::Find;

Monty> find (\&process_file,".");

Monty> sub process_file {
Monty> if (/\.hdr/) {
Monty> print "$File::Find::name\n";
Monty> open HDR_FILE, "<$File::Find::name" or die "Can't open file
Monty> for input: $!\n";
Monty> ...etc.

Monty> It prints the correct file name, complete with relative path, but it
Monty> dies on the open statement every time. What am I doing wrong?

You are opening $File::Find::name while still in the context of the
callback. You should either (a) put $File::Find::name into an array
to process when everything is done or (b) use $_ instead of $File::Find::name,
which is properly adjusted for the current directory.

File::Find does a whole lot of chdir'ing. So you have to comply.

print "Just another Perl hacker,"; # the original
 
R

Randal L. Schwartz

Henry> This, for example, is based on your code and works on my Win XP machine. (I've
Henry> replaced your "hdr" extension with "doc" for convenience).

Try an example with a subdir, and it won't.
 
M

Monty

Ok, my apologies for not getting back to anyone over the weekend.

I've had a chance to look over the solutions and I've implemented some
additional troubleshooting steps, but the result is the same.

Henry Law: you pretty much have verbatim what I've coded.
John Krahn: I replaced $File::Find::name with $_ and got the same
results.

There are no spaces in any of the file names. I also verified there
were no trailing spaces by doing an ls -aF on all the files.

How about setting the depth of the find()? The documentation leads me
to believe that the depth is infinite (not really, but such as that
is) by default, but I wonder is that really the case? This find()
I've coded has to go two directories deep before it finds a matching
file.

Thanks
 
M

Monty

To all who have responded with potential solutions, I thank you for
your interest.

I did find a solution to my problem once I understood more of the
documentation. I coded a hash with the process name and the no_chdir
option set to 1, and everything works as I expected. The call to find
then becomes find(\%refhash,".") and the script appears to find, open,
and process all the files in all the subdirectories (there are 256 of
them, and a count within the script agrees with that).

Thanks again for all your input.
Monty
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,281
Latest member
Pedroaciny

Latest Threads

Top