Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Using wildcards to open files.

by starface245 (Novice)
on Oct 25, 2012 at 15:37 UTC ( #1000889=perlquestion: print w/ replies, xml ) Need Help??
starface245 has asked for the wisdom of the Perl Monks concerning the following question:

#!/usr/bin/perl @files = glob("*.msg"); foreach $file(@files) { $cmd = "perl script.pl < $file"; system($cmd); }
I want to open all .msg files cause I have thousands. I get error "The system cannot find the file specified"

Comment on Using wildcards to open files.
Download Code
Re: Using wildcards to open files.
by kennethk (Monsignor) on Oct 25, 2012 at 15:48 UTC
    Do your file names have characters that need escaping or quoting, e.g. $cmd = "perl script.pl < '$file'";? Have you actually tested that the code as posted fails in your context? It works for me for some simple test systems.

    The simplest solution from my perspective would be to avoid shelling and modify script.pl to process multiple files. That will give you access to the actual diagnostics and remove a layer of misdirection.

    Update: If you can't modify script.pl for whatever reason, you can handle the file opens and piping yourself with something like:

    #!/usr/bin/perl -w use strict; my @files = glob("*.msg"); foreach my $file(@files) { open my $in, '<', $file or die "Open fail on $file: $!\n"; my @lines = <$in>; open my $out, '|-', 'perl script.pl' or die "Piping fail: $!\n"; print $out @lines; }
    Note that making those variables lexical to the loop (my) is significant, and you will likely need to explicitly close the filehandles otherwise. See |- in open or Safe Pipe Opens for some background.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Using wildcards to open files.
by muba (Priest) on Oct 25, 2012 at 15:50 UTC

    Do any of those .msg files have spaces in their names?

      Yes it does have spaces in the name.
        That's causing your problem. You are only using the chunk before the first space for each file.

        I haven't had a chance to test this in your exact usage situation, but try the following. It replaces spaces in the file names with escaped spaces.

        #!/usr/bin/perl @files = glob("*.msg"); foreach $file(@files) { $file =~ s/ /\\\ /g; $cmd = "perl script.pl < $file"; system($cmd); }
Re: Using wildcards to open files.
by aitap (Deacon) on Oct 25, 2012 at 16:00 UTC
    You shouln't use one-argument form of system in such unsafe way (imagine somebody running in that directory: touch file \;\ -rf\ \* and thus creating a file named file; rm -rf *). Use quotemeta to quote special characters or use IPC::Run and pass arguments and file redirections as list elements.
    Sorry if my advice was wrong.
Re: Using wildcards to open files.
by kcott (Abbot) on Oct 25, 2012 at 16:41 UTC

    G'day starface245,

    That's not really enough information to provide a definitive answer.

    Do you get that error once or multiple times? Is script.pl in the same directory as the *.msg files or accessible via $PATH? Have you tried anything to track down why the file(s) can't be found? Is the error being emitted by the code you posted or script.pl? Can you show us the code in script.pl?

    You could try something like the following (redirecting the output to a temporary file and searching for No such file or directory).

    $ perl -e ' use strict; use warnings; my @files = glob("*.msg"); for my $file (@files) { my $cmd = "ls -l $file"; system($cmd); } ' -rw-r--r-- 1 ken staff 10 26 Oct 03:01 a.msg -rw-r--r-- 1 ken staff 10 26 Oct 03:01 b.msg -rw-r--r-- 1 ken staff 10 26 Oct 03:02 c.msg

    With a script.pl like this:

    $ cat script.pl while (<>) { print "$_\n"; }

    This code works fine for me:

    $ perl -e ' use strict; use warnings; my @files = glob("*.msg"); for my $file (@files) { my $cmd = "perl script.pl < $file"; system($cmd); } ' Message A Message B Message C

    But I also get the same output with a single line:

    $ perl script.pl *.msg Message A Message B Message C

    Consider whether you really need thousands of shell and Perl processes if a single Perl process would do the same job.

    -- Ken

      Your code works for me, how do I escape with filenames that has spaces and special characters? such as "A_name sub.msg"

        As aitap said above, quotemeta will do that, a la my $escaped  = quotemeta($file); or even $cmd = "perl script.pl < \Q$file\E";


        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Using wildcards to open files.
by brap (Pilgrim) on Oct 26, 2012 at 13:31 UTC

    Hi starface245,

    The error message you provided leads me to believe you're on a Windows system. If that's not the case, this might not work, so feel free to disregard.

    Putting the file name itself in double quotes might be the answer here.

    $cmd = "perl script.pl < \"$file\""; (somewhat tested)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (9)
As of 2014-07-31 21:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (253 votes), past polls