views:

342

answers:

2

Well, I know this is another newbie question but I'm very frustrated and I'm looking to be enlightened again. With the guidance of you guys, I've already learnt how to use the glob function to read the contents of each file in a directory. Now I'm trying the readdir-foreach combination to do the same thing but I keep receiving "Cannot open file: Permission denied" error. Why is this happening with the same directory , the same files and the same me as Administrator. Can someone kindly show me what I'm doing wrong? Thanks.

The following code uses the glob function and it works:

#! perl
my $dir = 'f:/corpus/';
my @files = glob "$dir/*";
foreach my $file (@files) {
open   my $data, '<',"$file" or die "Cannot open FILE";
while(<$data>) {
...}

The following code fails and the error message says "Cannot open FILE: Permission denied". But why?

#! perl
my $dir = 'f:/corpus/';
opendir (DIR,'f:/corpus/') or die "Cannot open directory:$!";
my @files=readdir(DIR);
closedir DIR;
foreach my $file (@files) {
open   my $data, '<',"$file" or die "Cannot open FILE:$!";
while(<$data>) {
...}
+6  A: 

The readdir() function returns only the file's name, not a full path. So you are trying to open e.g. "foo.txt" instead of "f:\corpus\foo.txt".

Andy Ross
Just to add a possible solution: `use File::Spec; open my $data, '<', File::Spec->catfile($dir, $file);`
ephemient
Even better to use something like File::Next or Path::Class.
jrockway
Thank you Andy for your clarification! This makes perfect sense. and thank you ephemeient and jrockway. I'm now trying the File::Next fix.
Mike
I tried ephemeient's fix in combination with bobbymcr's filter and it worked great :)
Mike
Had trouble using File:Next fix, though. Perl gave me an error message saying something like "Cannot locate file/next.pl". Guess it's because the File::Next module hasn't been installed.
Mike
@Mike File::Slurp::read_dir() is also useful.
FM
@FM, thank you for the pointer. I'll give it a try.
Mike
+4  A: 

You should keep in mind that readdir returns directory names and file names. Most likely you are attempting to open one of the special directory entries . or .. which you generally need to filter out if you're using these functions:

foreach my $f (@files)
{
    # skip special directory entries
    if ($f ne '.' && $f ne '..')
    {
        # ...
        print "$f\n";
    }
}

Also note Andy Ross' suggestion that this will only return the relative path, not the full path.

bobbymcr
Mike
I think your code had both problems and the combination of the two got you the answer you needed. "Permission denied" is definitely the error you get when you attempt to open a directory with open(). Try `open(FILE, "<.") or die "Cannot open FILE:$!";` and see it in action...
bobbymcr
Ah, bobbymcr, you are probably right. Without the filter you suggested, I have the warning that looks something like this: readline() on closed filehandle. Thank you :)
Mike