Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Re^2: Passing commands to subroutines

by citromatik (Curate)
on Jul 01, 2009 at 17:11 UTC ( #776508=note: print w/replies, xml ) Need Help??

in reply to Re: Passing commands to subroutines
in thread Passing commands to subroutines

Hmmm... the original code redirects the system call:

executeComm ("program $ref_file > $outfile");

is there a way to use redirection in a system call using the multiple-arg version? this doesn't work: system ($program, $ref_file, ">",$outfile)


Replies are listed 'Best First'.
Re^3: Passing commands to subroutines
by ikegami (Patriarch) on Jul 01, 2009 at 18:45 UTC

    Your whole reason to use the multiple argument version of system was to avoid having the your arguments treated as anything but literal text.

    And now you're asking why it doesn't work when the code does exactly that.

    If you want redirection, you'll either have to build a shell command or do it yourself (IPC::Run, IPC::Run3, IPC::Open2, IPC::Open3, etc.)

Re^3: Passing commands to subroutines
by graff (Chancellor) on Jul 02, 2009 at 04:43 UTC
    Given that you're facing a problem with tricky file names, the easiest substitute I could imagine for fixing a line of code like this:
    system("program $ref_file > $outfile");
    would be to do it like this:
    open( PROG, "-|", "program", $ref_file ) or die "can't launch 'program +' on $ref_file: $!\n" open( OUT, ">", $outfile ); while (<PROG>) { print OUT; } close PROG; close OUT;
    That ought to take any sort of goofy file name safely in stride (for both input and output files).
      Probably easier to use one of the IPC:: modules, maybe IPC::Cmd
Re^3: Passing commands to subroutines
by JavaFan (Canon) on Jul 01, 2009 at 17:29 UTC
    You'd use fork and exec. Did you read the perlipc manual page I suggested? It contains code that does what you want which you can copy and adjust. I'm not going to cut and paste it for you.
Re^3: Passing commands to subroutines
by repellent (Priest) on Jul 03, 2009 at 22:57 UTC
    Multiple-arg system() doesn't quite work like that (read this). Redirection using the shell metacharacter ">" is handled by the shell, which reads the entire string "program $ref_file > $outfile", parses it, and executes the command with redirection.

    When you do multiple-arg system, you're going raw and skipping the shell (usually). Redirections have to be performed manually and you'll lose some convenience you get with using a shell. Example:
    sub executeComm { my ($outfile, @comm) = @_; print "cmd: <", join("> <" => @comm), ">\n"; # manual redirection - dup(2) STDOUT first open(my $ORIGSTDOUT, ">&" . fileno(*STDOUT)) or die $!; open(*STDOUT, ">", $outfile) or die $!; # run it! my $exit = system @comm; # restore STDOUT open(*STDOUT, ">&=" . fileno($ORIGSTDOUT)) or die $!; print "exit: ", $exit, "\n"; } print "before\n"; executeComm($outfile, $program, $ref_file); print "after\n";

    If you really want a quick-and-dirty fix for your "whitespace-in-filename" problem, place single-quotes around the filenames, as in:
    executeComm ("program '$ref_file' > '$outfile'");

    Now make sure you don't have single-quotes in the filenames...
Re^3: Passing commands to subroutines
by Anonymous Monk on Jul 01, 2009 at 17:21 UTC
    Have you read 'perldoc -f system'?
    system "foo >bar";
    invokes the shell, and it is the shell which does redirection (> <)
      <blocquote>Have you read 'perldoc -f system'?

      Yes... that is why I am asking: you are calling system with 1 argument... can you please give me an example like that one (with redirection) using the multiple-arg version?


Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://776508]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2023-12-03 10:25 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (20 votes). Check out past polls.