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?
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.