How do I get unmodified command line arguments to & ldquo; wrap & rdquo; another command-line tool?

advertisements

I want to write a script foo which simply calls bar with the exact same arguments it was called with, using Bash or Perl.

Now, a simply way to do this in perl would be

#!/bin/perl

my $args=join(' ', @ARGV);
`bar $args`;

However, the values in ARGV have already been processed by the shell, thus if I call

 foo "I wonder, \"does this work\""

bar would get called like this

 bar I wonder "does this work"

How can I obtain the original command line so that I can simply pass it on verbatim?


You can't get the arguments to the perl executable before they were processed by the shell. You can, however, ensure that the shell doesn't process them again:

system('bar', @ARGV);

vs.

system("bar @ARGV");

See perldoc -f system:

If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is "/bin/sh -c" on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to "execvp", which is more efficient.

If you need to read the output of the program, use a process handle and pass the arguments in the same way (without interpolation):

open my $barhandle, '-|', 'bar', @ARGV or die "Can't call bar: $!";
while (my $line = <$barhandle>)
{
    # do something with $line...
}
close $barhandle;

There are lots of ways you can call out to a program in Perl; see What's the difference between Perl's backticks, system, and exec? for a good overview of the major options.