Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

A bizarre way to get a list of filenames

by kiz (Monk)
on Aug 05, 2019 at 14:52 UTC ( [id://11103942]=perlquestion: print w/replies, xml ) Need Help??

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

So a colleague asked to to help with a wee perl problem, and his code has the following line:

my @xml_files = <*.xml>

He says it gives him a list of XML files .... say what?

Can someone explain this to me? This is a whole new use of the diamond operator I've not come across before!

(His question was "how do I add text files to this list?"... answer: make 2 lists & join them.. )


-- Ian Stuart
A man depriving some poor village, somewhere, of a first-class idiot.

Replies are listed 'Best First'.
Re: A bizarre way to get a list of filenames
by holli (Abbot) on Aug 05, 2019 at 14:56 UTC
    glob
    In list context, returns a (possibly empty) list of filename expansions on the value of EXPR such as the standard Unix shell /bin/csh would do. In scalar context, glob iterates through such filename expansions, returning undef when the list is exhausted. This is the internal function implementing the <*.c> operator, but you can use it directly. If EXPR is omitted, $_ is used. The <*.c> operator is discussed in more detail in I/O Operators in perlop.


    holli

    You can lead your users to water, but alas, you cannot drown them.
Re: A bizarre way to get a list of filenames
by LanX (Saint) on Aug 05, 2019 at 14:55 UTC
    It's called file-glob and is using the same diamond operator like readline

    And yes I agree it's confusing °, and due to the scripting ("Bash on steroids") heritage of Perl4.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    °) even the parser is sometimes confused, because it decides based on the inner pattern which operator is meant.

      even the parser is sometimes confused

      Nitpick: Unlike other cases, such as map or //, I think the rules for when <...> is readline vs glob are pretty clearly spelled out in I/O Operators.

      kiz: Note that using glob has several caveats, described in To glob or not to glob. In this particular example that you showed in your post, it's probably fine.

        > pretty clearly spelled out in I/O Operators

        here I agree with the docs

        These days, it's considered cleaner to call the internal function directly as glob($foo), which is probably the right way to have done it in the first place .)

        I passively remember very hairy edge cases here, and sometimes people try to overload <> for their own iterator use and fail because of edge cases. It's our main iterator operator after all.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: A bizarre way to get a list of filenames
by davido (Cardinal) on Aug 05, 2019 at 15:43 UTC

    The answers to most "how does this operator work?" questions can be found in perlop. In this case it's described in the IO Operators section of that document, where this is explained:

    If what's within the angle brackets is neither a filehandle nor a simple scalar variable containing a filehandle name, typeglob, or typeglob reference, it is interpreted as a filename pattern to be globbed, and either a list of filenames or the next filename in the list is returned, depending on context. This distinction is determined on syntactic grounds alone. That means <$x> is always a readline() from an indirect handle, but <$hash{key}> is always a glob(). That's because $x is a simple scalar variable, but $hash{key} is not--it's a hash element. Even <$x > (note the extra space) is treated as glob("$x ") , not readline($x).

    The document continues for a couple more paragraphs explaining in better detail what globbing is, and how it works with the diamond operator. And of course now we have the "how does the glob() function work?" question, which is answered by perldoc -f glob.

    The original question of "how do I add text files to this list?" can be answered by doing two globs:

    my @list = (<*.xml>, <*.txt>);

    Or by pushing elements from list two onto the array, or by using traditional shell file expansion mechanisms, described in File::Glob:

    my @list = <*.{xml,txt}>

    Dave

      or by using traditional shell file expansion mechanisms

      I'm glad you didn't suggest <*.xml *.txt> :-) Splitting its arguments on whitespace by default is IMHO one of the caveats of glob.

        Truth be known, I tested the splitting on whitespace approach while composing the response and deemed it to work in this case, but to be too fragile to bother introducing as another option.


        Dave

Re:A bizarre way to get a list of filenames
by hippo (Bishop) on Aug 05, 2019 at 15:03 UTC

    perldoc -f glob gives examples of using the angle brackets in this manner. It also refers to I/O-Operators in perlop which has some more on this towards the end of that section. That should cover most of it but if there's something you're still not sure about please ask further.

Re: A bizarre way to get a list of filenames
by Your Mother (Archbishop) on Aug 05, 2019 at 15:11 UTC

    Sidenote based on this–

    ("how do I add text files to this list?"... answer: make 2 lists & join them.)

    join is a proper operator as well as a concept and it’s definitely not what you want here. push @files, @xml_files, @text_files; or my @files = ( @xml_files, @text_files ); or some variety along those lines is more what you’ll want. You might already know this, I only mention it because of “join them.”

Re: A bizarre way to get a list of filenames
by Lotus1 (Vicar) on Aug 05, 2019 at 15:08 UTC
    (His question was "how do I add text files to this list?"... answer: make 2 lists & join them.. )

    There is also the push function if you would like to push items or a list onto the end of the array. Unshift will add to the beginning.

Re: A new to me way to get a list of filenames
by Anonymous Monk on Aug 06, 2019 at 02:11 UTC
    Hi

    Meet B::Deparse, the clue bringer

    $ perl -MO=Deparse -e " my @xml_files = <*.xml> " use File::Glob (); my(@xml_files) = <*.xml>; -e syntax OK

    File::Glob...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11103942]
Approved by holli
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (8)
As of 2024-04-18 13:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found