views:

162

answers:

3

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?

+11  A: 

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 http://stackoverflow.com/questions/799968/perl-backtics-vs-system-vs-exec for a good overview of the major options.

Ether
One consideration being, of course, that the return value from <code>system()</code> is the return value from the execution of the program, not the output from the program. It may be necessary to redirect output to a file and read the file, if you're trying to collect its output.
atk
@atk: in that case, you can use a process handle.
Ether
no, in that case you use IPC::Run or IPC::Cmd
ysth
@ysth: indeed, and we've even gone over this before: http://stackoverflow.com/questions/799968/perl-backtics-vs-system-vs-exec
Ether
Thanks for the detailed answer :)
Paul Dixon
+3  A: 

It's extremely simple. Check out the system(LIST) variant of system calls.

system('bar', @ARGV);

perldoc -f system

tsee
+3  A: 

In bash:

exec bar "$@"

This preserves the spacing in the arguments. I/O redirection, though, is not an argument within the meaning of the term (but the I/O redirection done for the original invocation would persist to the invoked 'bar' command unless you change it).

Jonathan Leffler