Search code examples
regexcsvperlparsingglob

Unable to Parse file correctly; Glob not working


I am trying to write a Perl script that basically checks if a particular file matching a regex exists in a particular directory. Here is my code:

use strict;
use warnings;

system ("grep PATH $ENV{MODEL_ROOT}/<....>/paths.tcl > \$MODEL_ROOT/hip_paths.csv");
system("sed -i 's/) /,/g' \$MODEL_ROOT/paths.csv");
system("sed -i 's/set G_L.*,//g' \$MODEL_ROOT/paths.csv");

my @glob;

my $file = "$ENV{MODEL_ROOT}/paths.csv" or die "CSV File is not present\n";
open(my $file_data, '<', $file) or die "Could not open '$file' $!\n";

while (my @line = <$file_data>) {
  system ("printf \"@line\" >> fields"); #For debug
  foreach my $path (@line)
 {   
     $path =~ m/^.*proj\/(.*)\/<blah>/; #To find 'name'
     if (glob ("$path/*0p765v_125c*.ldb")) #Check if file exists in $path with said pattern
     {   
            @glob = glob ("$path/*0p765v_125c*.ldb");
            print "File exists for $1 in path $path: @glob\n"
     } 
     else 
     {
        print "Does not exist for $1 in path $path\n";
     } 
  }
}
close $file_data

paths.csv looks like this: (Cant post actual path due to TM and C issues)

/(path-to-proj)/proj/name1/version1/abc  
/(path-to-proj)/proj/name2/version2/abc  
/(path-to-proj)/proj/name3/version3/abc  
/(path-to-proj)/proj/name4/version4/abc  
/(path-to-proj)/proj/name5/version5/abc   

(path to proj) is alphanumeric,
proj is alphabets only,
name<> is alpha-numeric and may contain underscores,
version<> is alpha-numeric

I know that all of these paths have a file that matches said pattern. However, the result of my code is something as shown below:

File exists for name1 in path /(path-to-proj)/proj/name1/version1/abc
: /(path-to-proj)/proj/name1/version1/abc
Does not exist for name2 in path /(path-to-proj)/proj/name2/version2/abc

File exists for name3 in path /(path-to-proj)/proj/name3/version3/abc
: /(path-to-proj)/proj/name3/version3/abc
Does not exist for name4 in path /(path-to-proj)/proj/name4/version4/abc

The results alternate between 'Exists' and 'Does not exist'. What am I doing wrong?


Solution

  • Operators (such as glob) function differently depending on whether they are evaluated in scalar context or list context.

    glob in scalar context acts as an iterator. It returns the next match until it returns undef to indicate there is nothing left to return. It doesn't matter if the argument changes.

    $ perl -e'for (1..7) { my $glob = glob("*"); CORE::say "$_ $glob"; }'
    1 a.xml
    2 b.xml
    3 
    4 a.xml
    5 b.xml
    6 
    7 a.xml
    

    You don't want that. You want to call it in list context. So replace

    if (glob ("$path/*0p765v_125c*.ldb")) {
            @glob = glob ("$path/*0p765v_125c*.ldb");
    

    with

    if ( my @ldb_paths = glob("$path/*0p765v_125c*.ldb") ) {
    

    or

    if ( my ($ldb_path) = glob("$path/*0p765v_125c*.ldb") ) {
    

    The second option gets just the first match, ignoring the rest. The parens on the left-hand side of the assignment are crucial to creating the necessary list context for the right-hand side.