chmod
chmod

Reputation: 95

Perl: open files from array and read one by one

I have an array in Perl that looks like this:

 my @dynfiles = ('dyn.abc.transcript', 'dyn.def.transcript', 'dyn.ghi.transcript', 'dyn.jkl.transcript');

I'm trying to open these files and read them one by one. For this I have a code that looks like this:

foreach my $dynfile (@dynfiles) {
    print "$dynfile\n";
    open my $fh , '<', $dynfile or die "Could not open file\n";
    my %data;
    $data{$dynfile} = do {
        local $/ = undef;
        while (my $line = <$fh>) {
            chomp $line;
            if ($line =~ m/Errors:\s+0/) {
                print "Dyn run status: PASS\n";
            } else { 
                print "Dyn Run status : FAIL\n";
            }
        }
        close $fh;
    }
}

And I get this error as output:

dyn.bxt.transcript
Dyn run status: FAIL
dyn.cnl.transcript
17:25:19 : -E- Could not open dyn.cnl.transcript

So my concern is that it isn't reading the files in the array at all. Also, this file dyn.bxt.transcript had this string Errors : 0 in it, but I still get Dyn run status: FAIL in the output. Am I doing anything wrong here? I'm using a simple pattern match, not sure where the problem is..Kindly help.

Thanks in advance!

Upvotes: 3

Views: 251

Answers (3)

hmatt1
hmatt1

Reputation: 5139

After viewing reading your code and debugging in chat, I would probably go with something like this:

sub dynamo_check {

    opendir(my $dh, $log_file) or die "can't opendir $log_file: $!";
    my @dynfiles = grep { /^dynamo.*transcript$/ && -f "$log_file/$_" } readdir($dh);
    close $dh;

    foreach my $dynamofile (@dynfiles) {
        print "Checking file: $dynamofile\n";

        open my $fh, '<', $log_file . $dynamofile or die "$!\n";

        my $passed = 0;

        while(my $line = <$fh>) {
            if ($line =~ m/Errors\s*:\s*0/i) {
                $passed = 1;
                last;
            }
        }
        if ( $passed == 1 ) {
            print "Dynamo run status: PASS\n";
            $data{$dynamofile} = "pass";
        }else {
            print "Dynamo run status: FAIL\n";
            $data{$dynamofile} = "fail";
        }
    }
    print Dumper(\%data);
}

Summary of changes:

  • Add on $! to get a better error message as reference in perlvar
  • Use grep and readdir to find the files you want to read instead of hard coding it.
  • Prepend the directory path to the file name when we open the files.
  • Remove the do block;
  • Set the values in %data to pass or fail.
  • No need to use chomp here.
  • No need to set local $/ = undef;, we can go through the lines one by one and break out of the while loop with last when we find the Errors line.

Upvotes: 2

clt60
clt60

Reputation: 63902

You can reduce the code using some well tested modules. For example using one of my favourite Path::Tiny, you could write:

use 5.014;
use warnings;
use Path::Tiny;

my @dynfiles = map { "dyn.$_.transcript" } qw(abc def ghi jkl);
say "Dyn run status: ",
    (path($_)->slurp =~ /error\s*:\s*0\b/i)
        ? "PASS"
        : "FAIL"
    for (grep {-f} @dynfiles);

Upvotes: 1

brian d foy
brian d foy

Reputation: 132792

First, let Perl tell you why it couldn't open a file:

open my $fh , '<', $dynfile or die "Could not open file $!\n";

I notice that your error message references dyn.bxt.transcript and dyn.cnl.transcript that are not in your @dynfiles. It helps is you build a complete and minimal script with sample inputs.

Then you are undefining the input record separator, after which you use a while which should only ever return the single line of the entire file. That's typically a bad thing.

Next, if looks as if your pattern doesn't match the string Errors : 0 that has a space in it.

        if ($line =~ m/Errors\s*:\s+0/) {

I'm not sure what you're doing with the do. That returns the last evaluated expression, which in your case is close $fh. But, that %data hash disappears at the end of each iteration of the block. Again, strip out everything that isn't part of investigating this problem.

Upvotes: 2

Related Questions