For one, one can submit a list to qx
; it gets interpolated into a string and then passed to either execvp
or a shell (see qx, and the second part of this post and comments). And if you need a shell then presumably that string contains shell metacharacters so it goes via shell.
my @cmd = qw(ls -l "dir with spaces");
#my @cmd = qw(ls -l "dir with spaces" > outfile);
my @out = qx(@cmd);
print for @out;
I make a "dir with spaces"
directory with a file in it to test. (For a command with quotes in it a shell does get used.)
Next, I would in principle recommend a module to compose those shell commands, instead of going through a nail-biter to correctly escape and pass it all, like String::ShellQuote
use String::ShellQuote qw(shell_quote);
my @cmd = ('ls', '-l', q(dir with spaces));
my $quoted = shell_quote(@cmd);;
my @out = qx($quoted);
#my @out = qx($quoted > outfile);
print for @out;
I use the q(...)
operator form of single quotes to demonstrate another way (also useful for including single quotes); it is not necessary for this simple example. One still need be careful with details; that's in the nature of using complex external commands and cannot be fully avoided by any approach or tool.
As for running bash
, note that normally sh
delegates to a default-of-sorts shell on your system, and on many systems it is bash
that is used. But if it isn't on yours, one way to use bash -c
in the command would be to first prepare the command and then add that to the qx
string
my @cmd = ('ls', '-l', q(dir with spaces));
my $quoted = shell_quote(@cmd);
my @out = qx(bash -c "$quoted");
#my @out = qx(bash -c "$quoted" > outfile);
print for @out;
A couple more notes I'd like to offer:
That qx
is an ancient demon. How about using modern tools/modules for running external commands? There may be a little more to do in order to prepare your involved bash strings but then everything else will be better. Options abound. For example
Why use external commands, with Perl's (far) superior richness? It's a whole, very complete, programming language, vs. the command-interpreter with some programming capabilities. If you need shell's capabilities why not run just those things via the shell and do all else in Perl?