Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

glob behavior

by vagabonding electron (Hermit)
on Mar 20, 2012 at 08:02 UTC ( #960545=perlquestion: print w/ replies, xml ) Need Help??
vagabonding electron has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
I cannot explain the following behavior of glob in the script.
Given is a directory U:/TEMP/TEMP with three subdirectories /A, /B and /C.
Each directory contains a file:
U:/TEMP/TEMP/A/Test01.txt U:/TEMP/TEMP/C/Test03.txt U:/TEMP/TEMP/B/Test02.txt
If I write the script the following way:
#!/usr/bin/perl use strict; use warnings; my %address = ( A => qq{U:/TEMP/TEMP/A}, B => qq{U:/TEMP/TEMP/B}, C => qq{U:/TEMP/TEMP/C}, ); for my $t (keys %address) { print "$t : $address{$t} : ", glob ("$address{$t}/Test*"), "\n"; }
then it prints as shown:
A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt
If I write it in the form:
#!/usr/bin/perl use strict; use warnings; my %address = ( A => qq{U:/TEMP/TEMP/A}, B => qq{U:/TEMP/TEMP/B}, C => qq{U:/TEMP/TEMP/C}, ); for my $t (keys %address) { my $file = glob ("$address{$t}/Test*"); print "$t : $address{$t} : $file, \n"; }
then the output is as follows:
A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt, Use of uninitialized value $file in concatenation (.) or string at ... + line 15. C : U:/TEMP/TEMP/C : , B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt,
Why it behaves itself different?
Thanks in advance.
VE

Comment on glob behavior
Select or Download Code
Re: glob behavior
by davido (Archbishop) on Mar 20, 2012 at 08:14 UTC

    In scalar context (your second example), glob will iterate over the items that match -- one item per call, and return undef if no more items remain. In list context (your first example), glob will return the entire list of items that matched, and that list could possibly be empty.

    So your two examples do differ in the context in which glob is being called, and that is documented to provide different behavior. Essentially, in scalar context glob acts like an iterator. In list context it doesn't iterate; it just returns a list.

    What I can't explain is why the list would be empty if nothing else changed.


    Dave

      What I can't explain is why the list would be empty if nothing else changed.
      From perlop:

      A (file)glob evaluates its (embedded) argument only when it is starting a new list. All values must be read before it will start over. I think this explains the effect we can see: The first time in the loop, the arguments for glob are evaluated and return one file name. The second time in the loop, the arguments are not evaluated again (since the list is not "exhausted" yet). Instead, glob tries to find the next file, but there is none, and returns undef to signal this fact. On the third iteration, the arguments are evaluated again, yielding one filename.

      -- 
      Ronald Fischer <ynnor@mm.st>
        It seems to be the case since after I added
        U:/TEMP/TEMP/D/Test04.txt U:/TEMP/TEMP/E/Test05.txt
        it prints in the first version:
        A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt D : U:/TEMP/TEMP/D : U:/TEMP/TEMP/D/Test04.txt C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt E : U:/TEMP/TEMP/E : U:/TEMP/TEMP/E/Test05.txt B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt
        and in the second version:
        A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt, Use of uninitialized value $file in concatenation (.) or string at ... + line 17. D : U:/TEMP/TEMP/D : , C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt, Use of uninitialized value $file in concatenation (.) or string at ... + line 17. E : U:/TEMP/TEMP/E : , B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt,
        Thank you very much!
        What I do not understand though - to be honest - is why glob is not evaluated again on the second loop pass.
        VE
        Update: After reading perlop and your post twice I did catch it :-)
        Sometimes it takes longer to savvy.
        Thanks again!
Re: glob behavior
by Anonymous Monk on Mar 20, 2012 at 08:45 UTC

    Why it behaves itself different?

    It probably doesn't :) put both loops in the same file and see what happens

    Also, report your perl version and File::Glob version

      I use ActivePerl v.5.14.1 on WinXP.
      The version of File::Glob is 1.12

      Update: I changed the loop to:
      for my $t (keys %address) { my $file = glob ("$address{$t}/Test*"); print "$t : $address{$t} : $file, \n###\n"; print "$t : $address{$t} : ", glob ("$address{$t}/Test*"), "\n---\ +n"; }
      It prints:
      A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt, ### A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt --- Use of uninitialized value $file in concatenation (.) or string at ... + line 17. D : U:/TEMP/TEMP/D : , ### D : U:/TEMP/TEMP/D : U:/TEMP/TEMP/D/Test04.txt --- C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt, ### C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt --- Use of uninitialized value $file in concatenation (.) or string at ... + line 17. E : U:/TEMP/TEMP/E : , ### E : U:/TEMP/TEMP/E : U:/TEMP/TEMP/E/Test05.txt --- B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt, ### B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt ---
      ... and now after changing the line from
      my $file = glob ("$address{$t}/Test*");
      to
      my ($file) = glob ("$address{$t}/Test*");
      the output is as follows:
      A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt, ### A : U:/TEMP/TEMP/A : U:/TEMP/TEMP/A/Test01.txt --- D : U:/TEMP/TEMP/D : U:/TEMP/TEMP/D/Test04.txt, ### D : U:/TEMP/TEMP/D : U:/TEMP/TEMP/D/Test04.txt --- C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt, ### C : U:/TEMP/TEMP/C : U:/TEMP/TEMP/C/Test03.txt --- E : U:/TEMP/TEMP/E : U:/TEMP/TEMP/E/Test05.txt, ### E : U:/TEMP/TEMP/E : U:/TEMP/TEMP/E/Test05.txt --- B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt, ### B : U:/TEMP/TEMP/B : U:/TEMP/TEMP/B/Test02.txt ---

        Once again you're dealing with different contexts. my $file = glob ... evaluates glob in scalar context, rendering it an iterator function, and my ($file) = glob ... evaluates glob in list context, rendering it a list function that returns a list, which can be empty.


        Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://960545]
Approved by davido
Front-paged by MidLifeXis
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2014-08-30 09:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (291 votes), past polls