0

I want to call a perl script(B.pl) which will list the files available in the remote server from the main perl script(A.pl) by passing more than one optional arguments.

Since the arguments were optional, if I use backticks the arguments are getting assigned to wrong variables in B.pl.

If I use @list=system(B.pl, argv0, argv1, argv2); then though some arguments are undef it is getting correctly assigned in B.pl but the STDOUT is not getting assigned to @list in the calling script.

I am new to perl, please guide in this scenario. Is there any way to pass null arguments with backticks ?

In A.pl:

my @filelist = system( B.pl, $argv0, $argv1, $argv2, $argv3);
my @filelist1 = `B.pl $argv0 $argv1 $argv2 $argv3`;

In B.pl:

my $loc   = uc( $ARGV[0] );
my $msk   = uc( $ARGV[1] );
my $usr   = $ARGV[2];
my $usr1  = $ARGV[3];
AnFi
  • 10,493
  • 3
  • 23
  • 47
user1919581
  • 481
  • 2
  • 14
  • 32
  • `system` returns the callee's exit value, not what it printed. – darch Jul 04 '15 at 07:18
  • Please show how you are invoking `B.pl` and how you are assigning the arguments it receives. – darch Jul 04 '15 at 07:19
  • You should consider using the `--name val` notation for optional arguments, and use Getopt::Long to parse the command line. – ikegami Jul 04 '15 at 19:12

3 Answers3

5

You may use "zero length strings" ("" or '') as parameters inside back-ticks:

perl -e "print `perl -e 'print $ARGV[2]' 0 '' 2`"

OR use perl module for handling command line options e.g. Getopt::Std

AnFi
  • 10,493
  • 3
  • 23
  • 47
2

This is not a question about Perl so much as it is about the shell. You are trying to pass a bunch of parameters, some of which are optional. Fortunately, this is a well-understood problem. The answer is to pass named options instead of positional arguments. The standard way to do that in Perl is with Getopt::Long.

For example, in B.pl, you could say

use Getopt::Long;
my ($loc, $msk, $usr, $usr1);
GetOptions(
    "loc=s"     => \$loc,
    "msk=s"     => \$msk,
    "usr=s"     => \$usr,
    "usr1=s"    => \$usr1,
) or die "Something wrong with your options!";

And the invocation in A.pl would read:

my @filelist1 = `B.pl '--loc=$argv0' '--msk=$argv1' '--usr=$argv2' '--usr1=$argv3'`;

There are more sophisticated approaches. Per this answer, for example, we find out about IPC::Run.

Community
  • 1
  • 1
darch
  • 4,200
  • 1
  • 20
  • 23
1

Unfortunately, a safe version of the backticks operator or of readpipe doesn't exist. It has been on the perl TODO list for years!

But you can do it yourself easily using open:

open my $handle, '-|', 'B.pl', $argv0, $argv1, $argv2, $argv3
    or die "unable to run external command: $!";
my $output = do { local $/; <$handle> };
close $handle
    or die "unable to capture output from child command: $!";
$? and die "remote command exited with non zero return code: $?";
salva
  • 9,943
  • 4
  • 29
  • 57