wiredcontrol
wiredcontrol

Reputation: 168

Perl system command changes the variable values and throws error

I have the following script:

#! /bin/env perl 

use File::Basename;
my @log_files;
my $log_dir = "/tmp/";
my $path = "find_failing/";
$log_files[0] = (`find $path -name compile.log -print0`)[0];
$log_files[1] = (`find $path -name sim.log     -print0`)[0];
my $rev = "100";

print "@log_files << \n";

foreach (@log_files) {
   if (-f $_) {
      chomp;
      my $dirn = sprintf "%s/%s.%s", $log_dir, basename ($_), $rev;
      chomp $dirn;
      my $cmd = "cp -v $_ $dirn";
      chomp $cmd;
      print "C: $cmd\n";
      system ($cmd);
      system ("cp", "-v", $_, $dirn);
      system ("echo");
   }
}

When I run this, I am getting the following output:

find_failing/simulation/tc_ctrl.rtl/compile/compile.log find_failing/simulation/tc_ctrl.rtl/test_prbs.nrz.16.prbs23/sim.log << 
C: cp -v find_failing/simulation/tc_ctrl.rtl/compile/compile.log /tmp//compile.log.100
cp: missing destination file operand after `find_failing/simulation/tc_ctrl.rtl/compile/compile.log'
Try `cp --help' for more information.
`find_failing/simulation/tc_ctrl.rtl/compile/compile.log' -> `/tmp//compile.log'

C: cp -v find_failing/simulation/tc_ctrl.rtl/test_prbs.nrz.16.prbs23/sim.log /tmp//sim.log.100
cp: missing destination file operand after `find_failing/simulation/tc_ctrl.rtl/test_prbs.nrz.16.prbs23/sim.log'
Try `cp --help' for more information.
`find_failing/simulation/tc_ctrl.rtl/test_prbs.nrz.16.prbs23/sim.log' -> `/tmp//sim.log'

The print of the command shows the correct expansions of the variables as I intended. However, when run using the system (), it throws an error saying the destination is missing.

Further, when I issue the command by giving it as a list, the copy happens but the destination path is missing the ".$rev" that is part of the $dirn.

I ran with v5.8.8 and v5.24.0 and I'm getting the same output.

What is happening? Why is system () behaving this way?

Thank you.

Upvotes: 0

Views: 65

Answers (1)

ikegami
ikegami

Reputation: 385506

-print0 prints the paths followed by a NUL, so

  • $log_files[0] contains

    find_failing/foo/compile.log<NUL>find_failing/bar/compile.log<NUL>
    
  • $log_files[1] contains

    find_failing/foo/sim.log<NUL>find_failing/bar/sim.log<NUL>
    

Replace

$log_files[0] = (`find $path -name compile.log -print0`)[0];
$log_files[1] = (`find $path -name sim.log     -print0`)[0];

with

( $log_files[0] ) = split /\0/, `find $path -name compile.log -print0`;
( $log_files[1] ) = split /\0/, `find $path -name sim.log     -print0`;

or

$log_files[0] = `find $path -name compile.log -print0`;
$log_files[1] = `find $path -name sim.log     -print0`;

s/\0.*//s for @log_files;

Upvotes: 2

Related Questions