Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

using wildcard character * in perlscript command line

by krusty (Hermit)
on Jan 28, 2005 at 15:14 UTC ( [id://425978]=perlquestion: print w/replies, xml ) Need Help??

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

The following works perfectly well to give me a list of all files in UNIX

Execute from command line as "> script.pl *"
#!/usr/bin/perl -w foreach (@ARGV){ print; }

This prints out
doc1.tmp doc2.tmp doc3.tmp

but in windows
*

How should I be executing the script in windows XP cmd.exe with the wildcard?


Thanks!
Kristina

Update: It worked like a charm. Thanks for your fast response Tanktalus and BrowserUk.

Replies are listed 'Best First'.
Re: using wildcard character * in perlscript command line
by Tanktalus (Canon) on Jan 28, 2005 at 15:18 UTC
    foreach my $arg (@ARGV) { foreach (glob $arg) { print; } }

    The expansion you're seeing is due to the unix shell expanding wildcards prior to giving them over to the command being run, while Windows thinks that each program should have to do that itself, duplicating the same code all over your system.

    Update:Taking BrowserUk's solution and combining it comes up with yet another WTDI... which, ashamedly, I should have done in the first place, since I use map for this type of thing all over the place in my own code.

    foeach (map { glob } @ARGV) { print; }

    (I prefer the block form of map, but you can do with that as you will.)

      There is an advantage to shell not expanding wildcards. It allows for doing: copy *.txt *.bak. To do the same in a shell which expand wildcards requires a loop in the shell, making it harder to run simple commands AND duplicating the same code all over your system.

      I wouldn't mind being able to do copy *.txt 's/\.txt$/.bak/'.

        You just have to quote the arguments, and they won't be expanded:

        move "*.txt" "*.html"

        Of course the move command displayed here is just an example, which you'd have to code yourself...

        Another sideeffect is that you don't end up with needing xargs or find -exec and all the similar solutions to work around wildcards that produce huge lists.

        The app. can choose--(IMO) should always choose--to use an iterator approach rather than a generator.


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.

        man 1 rename?

        For more complex cases there's the rename script distributed with Perl…

        Makeshifts last the longest.

        look for 'rename.pl' by Larry Wall. Does exactly what you want.

        Yes, I like that great feature in dos. It even works in norton commander: you select multiple files, press F6 (rename), and type a wildcard name such as ?????_0.* to rename all selected files.

      The expansion you're seeing is due to the unix shell expanding wildcards prior to giving them over to the command being run

      However, you don't have to use cmd as your shell under Windows. You can install bash or another shell that comes from UNIX. Then I would be very surprised if you couldn't enjoy nice wildcard expansion under that OS.

      foreach my $arg (@ARGV) { foreach (glob $arg) { print; } }
      (Nah!) Since wildcard expansion "should" happen before the args are passed to the script, I like to do it all at once as early as possible:
      BEGIN {@ARGV=map glob, @ARGV}
      And then the rest of code can plainly ignore what happened with no need of ad hoc interventions...
Re: using wildcard character * in perlscript command line
by BrowserUk (Patriarch) on Jan 28, 2005 at 15:19 UTC

    glob applied to @ARGV in a BEGIN block gives a reasonable approximation.

    perl -wle"BEGIN{ @ARGV = map glob, @ARGV } print for @ARGV" *

    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      I looked at this and thought, "no way, what if the script gets switches or other arguments that are not files (like script * -option), those arguments will get lost because they donīt match any filename.
      But they donīt. Can you explain why?

      holli, regexed monk
        Because glob() will simply pass-thru anything that doesn't need expansion, otherwise it would lose ordinary filenames. But if the 'option' might have the expandable characters '*' or '?' you will be in danger of losing _those_ options. glob('-f?') returns nothing (usually), though glob('-f') will simply return '-f'.

        If the value passed to glob doesn't contain a wildcard, it is passed through untouched.

        P:\test>perl -wle" print for glob '-debug' " -debug

        As for the why, if there is no file of that name existing, you'll need someone with the historical perspective (merlyn?).

        Maybe, just so that it doesn't affect non-wildcard parameters?


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.

        Perl's glob was originally implemented in terms of csh's. From man csh:

        If a word contains any of the characters *, ?, [ or { or begins with the character ~ it is a candidate for filename substitution, also known as globbing.

        If you use the bsdglob function from File::Glob (which is how glob is implemented nowadays), you can pick behaviour as desired.

        Makeshifts last the longest.

        For the same reason for which (depending on an option, really) *NIX shells (well, at least bash that I know) pass through any unmatched item.
Re: using wildcard character * in perlscript command line
by Overthruster (Initiate) on Jan 28, 2005 at 18:07 UTC
    Here's what I use...
    foreach $arg ( @ARGV ) { @files = glob $arg; foreach (@files) { ...
Re: using wildcard character * in perlscript command line
by Willworker (Acolyte) on Jan 28, 2005 at 19:20 UTC
    I ran into this same problem. In an older version (<5.0) of perl, "perl script.pl *.ext" worked the way I expected it to, by expanding the * wildcard, but after upgrading to perl 5.8, this no longer worked, so I had to do something like the examples already given (doing the globbing/*-expansion with a couple lines of code). Steve

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2024-04-25 09:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found