scain has asked for the wisdom of the Perl Monks concerning the following question:

Hello O Great and Powerful Monks,

I humbly come to you with a question from a co-worker. He came to me as the resident Perl (nearly) monk. He presented the following text code (minus use strict;, which I admonished him for). His goal was to write code that would go into several directories and get the one and only file in each directory that would satisfy the file glob. So, for example, in this code, the <test.txt> would be replaced with </home/scott/manydirs/$i/*test.txt>.

#!/usr/bin/perl -w use strict; my $EXON_IN; for (my $i=0; $i < 5; $i++){ $EXON_IN = <test.txt>; print "$i, -$EXON_IN-\n"; }
which produces this output:
[scott@blast test]$ ./test.pl 0, -test.txt- Use of uninitialized value in concatenation (.) or string at ./test.pl + line 7. 1, -- 2, -test.txt- Use of uninitialized value in concatenation (.) or string at ./test.pl + line 7. 3, -- 4, -test.txt-
Initially I said "context, context, context", as he did not think assigning a fileglob to a scalar should be any different than assigning to an array when there is only one result. I knew better on that score, but couldn't explain the above behavior. I read the relevent section of perlop2, but an explaination for this alternating behavior eludes me. My co-worker fixed this by assigning to an array, then only using the 0th element, but I would like to return with a clear reason for the behavior.

Submitted humbly for your consideration,

Scott

Replies are listed 'Best First'.
Re: Fileglob in scalar context question
by japhy (Canon) on Jun 30, 2001 at 00:23 UTC
    The <GLOB> (or glob()) operator, in scalar context, returns one element at a time. And since this is the same glob(), it retains its state (it knows what to return next). Since glob("foo.bar") returns just one element (and undef the next time to signify the end of the files found) you get the filename the first time, and then undef the next.

    japhy -- Perl and Regex Hacker
Re: Fileglob in scalar context question
by John M. Dlugosz (Monsignor) on Jun 30, 2001 at 00:40 UTC
    To continue the explaination by Japhy, I think you're confused that the return value is the same as the stuff between the angles. It's returning the file name, and since there are no wildcards, what else can it find?! It's not returning a fully-quallified name with path information added, if that's what you mean. You're essentially doing an "exists" test on that one file -- it will return that name back if it exists, undef otherwise, and meanwhile keep a persistant state.

    I don't know what to make of the persistant state. If you change the current working directory, how does one reset the state? If it contains a variable, and the variable changes, how do you know when to continue or start over?

    —John

      Actually, it returns "test.txt" even if the file doesn't exist.

              - tye (but my friends call me "Tye")
        Why would it do that?
      John,

      While you are probably right about being confused about "the stuff between the angles", the original program did have a wild card in it. In the first pass through the loop, it would look like </home/scott/manydirs/0/*test.txt>.

      However, on thinking about this problem more, I think I would rewrite the code to look like this:

      #!/usr/bin/perl -w use strict; my @EXON_IN = </home/scott/manydirs/[0-9]*/*test.txt>; foreach my $file (@EXON_IN){ #do whatever it was my coworker wanted to do #Greg, are you looking? }
      Which is probably what I would have done if I was doing this from scratch, but when presented with another's code, it is often hard to think of the "right" thing to do right away.

      Thanks,
      Scott