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 specified pattern, returning the next file name each time it is called or undef when there are no more files.
But, the iterating process only seems to work from within a loop. If it isn't in a loop, then it seems to start over immediately before all values have been read.
From the Perl docs:
In scalar context, glob iterates through such filename expansions, returning undef when the list is exhausted.
http://perldoc.perl.org/functions/glob.html
However, in scalar context the operator returns the next value each time it's called, or undef when the list has run out.
http://perldoc.perl.org/perlop.html#I/O-Operators
Example code:
use warnings; use strict; my $filename; # in scalar context, <*> should return the next file name # each time it is called or undef when the list has run out $filename = <*>; print "$filename\n"; $filename = <*>; # doesn't work as documented, starts over and print "$filename\n"; # always returns the same file name $filename = <*>; print "$filename\n"; print "\n"; print "$filename\n" while $filename = <*>; # works in a loop, returns next file # each time it is called
In a directory with 3 files...file1.txt, file2.txt, and file3.txt, the above code will output:
file1.txt file1.txt file1.txt file1.txt file2.txt file3.txt
Note: The actual perl script should be outside the test directory, or you will see the file name of the script in the output as well.
Am I doing something wrong here, or is this how it is supposed to work?
glob() function in Perl is used to print the files present in a directory passed to it as an argument. This function can print all or the specific files whose extension has been passed to it. Syntax: glob(Directory_name/File_type); Parameter: path of the directory of which files are to be printed.
glob - Perldoc Browser. In list context, returns a (possibly empty) list of filename expansions on the value of EXPR such as the Unix shell Bash would do.
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 :)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With