0

I get some strange behaviour searching for files using glob. (I think its intended, but I don't want it in my case)

I have 2 files named aaa:bbb and aaa:ccc.

I have code to see if files with prefix aaa:* exists. I do this with this code:

my $filelocation_special = "aaa";

if (glob($filelocation_special . ":*")) {
  # file(s) exists!
}

This works. However, if I run the same code again two more times glob returns undefined.

these are my returns: (most of the time anyway)

print STDERR "glob: " . glob($filelocation_special . ":*") . "\n";

# 1 run: aaa:bbb
# 2 run: aaa:ccc
# 3 run: 

What can I do to reset globto always just check if files with this prefix exists?

Maybe I should use some different check altogether, but I can't seem to find anything that is fast and just checks if the files exists.

A.D
  • 2,150
  • 3
  • 13
  • 19
  • It this `CORE::glob` or `:bsd_glob` from http://perldoc.perl.org/File/Glob.html? – simbabque Feb 01 '17 at 14:30
  • The requests come from our iOS app. So there is some delay between the code that runs. To run it 3 times takes around 5 seconds. – A.D Feb 01 '17 at 14:31
  • Assigning the result of `glob` to an array will fix this, and it's highly likely that you'll want to know the names of the files as well as just whether they exist. – Borodin Feb 01 '17 at 19:16

1 Answers1

3

if (glob(...)) is a call to glob in scalar context.

In scalar context, glob iterates through such filename expansions, returning undef when the list is exhausted.

So everytime you call glob in scalar context, with the same arguments, and from the same line of code, you will get a different result, and eventually you will get undef when the list of files that match your argument are exhausted.

To get your expression to mean "if there are files that match this pattern ...", you need to use list context somehow.

@tmp = glob(pattern)
if (@tmp) 

if (()=glob(pattern))

if (@{[glob(pattern)]})


Diversion: any of these also work (because @* are valid global array identifiers for many values of punctuation character *)
if (@@=glob(pattern))
if (@<=glob(pattern))
if (@:=glob(pattern))

and they can even be written like

if (@ <= glob(pattern))
if (@ := glob(pattern))

and so a few more candidates for secret operators are suggested.

@@ = EXPR       like the goatse operator, returns a count of elements
@ <= EXPR       in EXPR when EXPR is evaluated in list context; useful
@ := EXPR       when EXPR in scalar context does not do this
mob
  • 117,087
  • 18
  • 149
  • 283
  • Wow. That is some really wierd code. I tried it though. And it worked just the way I wanted it to. Thanks! – A.D Feb 01 '17 at 14:50
  • There's some good discussion on scalar glob at [this question](http://stackoverflow.com/questions/2633447/why-doesnt-perl-file-glob-work-outside-of-a-loop-in-scalar-context). – mob Feb 01 '17 at 15:04
  • 1
    Using symbolic identifiers like that is discouraged because they are reserved for Perl built-in variables. It is also highly inconsiderate to write code using undefined symbolic variables with spaces in unusual places, as most Perl programmers will be unable to parse it quickly. The obvious way to check the existence of files matching a `glob` pattern is with `if ( my @files = glob 'aaa:*' ) { ... }` where the array `@files` is defined only for the length of the `if` block. "secret operators" are mostly infantile toys rather than valid constructs for use in production software – Borodin Feb 01 '17 at 19:10