For those students seemingly having problems using glob() in HW3,
you're not alone. There appears to be a bug in perl itself when using
glob(). Specifically, errors can arrise when glob() is used more than once in
the same program. One specific error I've seen is that a second call to
glob() is returning undef, instead of whatever it should be returning.
There are two work arounds for this problem:
1) Only use glob() once in your code, and save its return value in a
scalar variable. For example, you may wish to save the expanded
directory name you'll be working from in $dir. Then any time you want
to access a file from that directory, instead of using glob() again, use the
string "$dir/$filename".
2) Use the function bsd_glob() instead of glob(). In order to do
this, you must put this line at the top of your code, below your shebang:
use File::Glob ':glob';
then replace all instances of glob() in your code with bsd_glob().
Anyone with questions or problems, please email me.
The following was sent at midnight Sunday night:
A further note on the glob issues from earlier today.
It seems this is not a bug as I originally believed, but a feature.
When glob() is used in scalar context within a loop, it returns each
successive match to the pattern that was given to glob(). For example, if a
directory contained:
file1.txt
foo.txt
bar.txt
and a loop contained
$filename = glob("*.txt");
then $filename would get file1.txt the first time, foo.txt the 2nd,
and bar.txt the third. On the fourth time through the loop, $filename
would be undef, to signal it had reached the end of pattern matches.
For the expansions you are likely doing in your program, ~userid only
has one match, so if there is a loop in which glob("~userid") is
evaluated, it will return undef on the 2nd, 4th, 6th, etc attempt.
In addition to the work arounds mentioned earlier, the 'preferred' way
of doing this is to force a list context when you are expecting only one
match to your glob. In other words, instead of
$filename = glob("~$user");
do
($filename) = glob("~$user");
A list context will force glob to return all its matches at once, so
the next time through the loop, it will get a full list of matches again.