According to the Perl documentation on file globbing, the <*> operator or glob() function, when used in a scalar context, should iterate through the list of files matching
The following code also seems to create 2 separate instances of the iterator...
for ( 1..3 ) { $filename = <*>; print "$filename\n" if defined $filename; $filename = <*>; print "$filename\n" if defined $filename; }
I guess I see the logic there, but it is kind of counter intuitive and contradictory to the documentation. The docs don't mention anything about having to be in a loop for the iteration to work.
(Scratching away at my rusty memory of Perl...) I think that multiple lexical instances of <*>
are treated as independent invokations of glob, whereas in the while loop you are invoking the same "instance" (whatever that means).
Imagine, for instance, if you did this:
while (<*>) { ... }
...
while (<*>) { ... }
You certainly wouldn't expect those two invocations to interfere with each other.
Also from perlop:
A (file)glob evaluates its (embedded) argument only when it is starting a new list.
Calling glob
creates a list, which is either returned whole (in list context) or retrieved one element at a time (in scalar context). But each call to glob
creates a separate list.
Here's a way to capture the magic of the <>
glob operator's state into an object that you can manipulate in a normal sort of way: anonymous subs (and/or closures)!
sub all_files {
return sub { scalar <*> };
}
my $iter = all_files();
print $iter->(), "\n";
print $iter->(), "\n";
print $iter->(), "\n";
or perhaps:
sub dir_iterator {
my $dir = shift;
return sub { scalar glob("$dir/*") };
}
my $iter = dir_iterator("/etc");
print $iter->(), "\n";
print $iter->(), "\n";
print $iter->(), "\n";
Then again my inclination is to file this under "curiosity". Ignore this particular oddity of glob()
/ <>
and use opendir
/readdir
, IO::All/readdir
, or File::Glob instead :)