王云龙
王云龙

Reputation: 71

Perl cannot find and open existing file file name even I can print out exactly the same file name

I'm having the following problem like this: I tried to traverse through all the sub-directory folders with numeric name, e.g.: 0/ 1/ 2/ ... and try to check files named like this: combine_0_arc combine_1_arc ... in which the number in between is the same as the sub-folder name which this file exists, and here's how I do it:

#!/usr/bin/perl -w
use strict;

opendir(DIR, "./") or die "Failed to open directory: $!\n";
my @DirName = readdir(DIR) or die "Unable to read current directory: $!\n";
#closedir(DIR);

foreach (@DirName){
    chomp;
    my $CurrentDir =$_;
    next if ($CurrentDir eq ".");
    next if ($CurrentDir eq "..");
    if($CurrentDir =~ /^\d+$/){
    #    print "Iteration directory: $CurrentDir\n";
        opendir(SUBDIR, $CurrentDir) or die "Unable to read current directory: $CurrentDir\n";
        my @SubDirFiles =  readdir(SUBDIR);
        foreach (@SubDirFiles){
            chomp;      
  #          if($_ =~ /combine_0_arc/){next;}      
            if($_ =~ /combine_\d+_arc$/){
                my $UntestedArc = $_;
           #     print "Current directory: $CurrentDir\n";
           #     print `pwd`."\n";
           #     print "Combine_arc_name:$UntestedArc\n";
                open (FH, "<", $UntestedArc) or die "Cannot open file $UntestedArc:$!\n";
            }
          }
        } 

It seems I'm getting the following error message: Cannot open file combine_0_arc:No such file or directory

and I tried to print out the folder name and the file name for each iteration it seems it's printing out correctly. I tried to chomp those trailing spaces or carriage returns for each file name or folder name but it seems it's not working. Can anybody explain me what's happening there? Thanks a lot!

Upvotes: 2

Views: 479

Answers (2)

zdim
zdim

Reputation: 66883

The readir returns bare file name, without the path. So add it

foreach my $CurrentDir (@DirName) {
    # ...
    opendir my $SUBDIR, $CurrentDir;
    my @SubDirFiles = map { "$CurrentDir/$_" } readdir($SUBDIR);

    foreach my $untestedArc (@SubDirFiles) 
    {
        if ($UntestedArc =~ /combine_${CurrentDir}_arc$/) {
             # ...
        }
    }
}

where the regex uses that directory's name, not any number.

Notes

  • readdir doesn't add a newline, no need to chomp (it doesn't hurt though)

  • use lexical filehandles

  • declare the loop variable (topicalizer) in the foreach statement

This answer assumes that your current working directory is the one with @DirName subdirectories.

Upvotes: 2

Steffen Ullrich
Steffen Ullrich

Reputation: 123320

readdir just returns the file names in the directory, i.e. the name relative to the directory given to the matching opendir. But, what you need for open is either the absolute name of the file or the name relative to the directory you are currently in (current working directory). Since opendir does not magically change the working directory (this could be done with chdir) the working directory is not the same as the directory scanned with opendir and thus the relative file you use within open can not be found within the current working directory.

Upvotes: 1

Related Questions