perlbackticksqx

use perl's qx{} / `...` operator with a list of arguments


system, exec, open '|-', open2, etc. all allow me to specify the command to run as a list of arguments that will be passed directly to execvp instead of run through a shell.

Even if perl is smart enough to run it directly if it looks like a "simple" command, that saves me the trouble of correctly shell-escaping the arguments with all the nasty pitfalls that it entails.

Example:

open my $out, '|-', $prog, @args;
system $prog, @args;
exec $prog, @args;

instead of

open my $out, "|$prog @args";
system "$prog @args";
exec "$prog @args";

Is there such an equivalent for the qx// operator? Or do you have to always do it by hand eg.

sub slurpcmd {
   open my $h, '-|', @_ or die "open $_[0]|: $!";
   local $/ unless wantarray;
   <$h>
}

Solution

  • It turns out that (unfortunately) this wasn't an overlook from my part -- the only solution really is to do it with open -| or use one of the external modules listed in the other answers.

    The backtick implementation (whether invoked by qx/.../, `...`, or readpipe) is deep down hardwired to accept a single string argument:

    PP(pp_backtick)
    {
        dSP; dTARGET;
        PerlIO *fp;
        const char * const tmps = POPpconstx;
        const U8 gimme = GIMME_V;
        const char *mode = "r";
    
        TAINT_PROPER("``");
        if (PL_op->op_private & OPpOPEN_IN_RAW)
            mode = "rb";
        else if (PL_op->op_private & OPpOPEN_IN_CRLF)
            mode = "rt";
        fp = PerlProc_popen(tmps, mode);
        ...
    

    Notice the POPpconstx which pops a single argument from the stack and the use of PerlProc_popen instead of PerlProc_popen_list.