Search code examples
perlglob

perl glob < > (star) operator returning unexpected results?


I am using the

my $file = <*.ext>;

function within Perl to test if a file exists (in this case, I need to know if there is a file with the .ext in the current working directory, otherwise I do not proceed) and throw an error if it doesn't. Such as:

my $file = <*.ext>;
if (-e $file) {
    # we are good
}
else {
    # file not found
}

As you can see I am bringing the input of the <*.ext> in to a scalar $variable, not an @array. This is probably not a good idea, but it's been working for me up until now and I have spent a while figuring out where my code was failing... and this seems to be it.

Seems that when switching directories (I am using "chdir", on a Windows machine) the current working directory switches properly but the input from the glob operator is very undefined and will look in previous directories, or is retaining past values.

I've been able to fix getting this to work by doing

my @file = <*.ext>;
if (-e $file[0]) {
}

and I'm wondering if anybody can explain this, because I've been unable to find where the return value of the glob operator is defined as an array or a scalar (if there is only one file, etc.)

Just trying to learn here to avoid future bugs. This was a requirement that it be in Perl on Windows and not something I regularly have to do, so my experience in this case is very thin. (More of a Python/C++ guy.)

Thanks.


Solution

  • perldoc -f glob explains this behavior

    In list context, returns a (possibly empty) list of filename expansions on the value of EXPR such as the standard Unix shell /bin/csh would do. In scalar context, glob iterates through such filename expansions, returning undef when the list is exhausted.

    So you are using iterator version which should be used with while to loop over it (all the way until it gets exhausted). As you clearly want to get only first value using list context you can,

    my ($file) = <*.ext>;