简体   繁体   中英

Windows cmd.exe command passed Perl system function needs double quotes in some cases?

The Windows cmd.exe command 'type \Test\hello.txt' must be surrounded with double quotes in order for the Perl system() function to execute it properly. I don't find this documented at https://perldoc.perl.org/functions/system or at https://perldoc.perl.org/perlport#system - is the requirement for double quotes on Windows documented anywhere?

The following sample code demonstrates the issue when run with command perl \my\perl\perlsystest in a Windows Command Prompt window on a Windows 10 Pro server at version 2004 (OS Build 19041.867) with Perl at level v5.26.3


$cmd='type \Test\hello.txt' ;   # Set Windows DOS command to be executed
system('ECHO '.$cmd) ;          # Display command to be executed
system($cmd) == 0               # Execute command - note "\Test\hello.txt not found" error but with $? == 0
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

$cmd='"'.$cmd.'"' ;             # Surround command string in double quotes
system('ECHO '.$cmd) ;          # Display command to be executed
system($cmd) == 0               # Execute command - note that command succeeds
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

$cmd='type \Test\10hello.txt' ; # Set Windows DOS command to be executed
system('ECHO '.$cmd) ;          # Display command to be executed -  note that "type \Teshello.txt" is echoed
system($cmd) == 0               # Execute command - note "\Test\hello.txt not found" error but with $? == 0
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

system('"ECHO '.$cmd).'"' ;     # Display command to be executed (with ECHO command in double quotes)
$cmd='"'.$cmd.'"' ;             # Surround command string in double quotes
system($cmd) == 0               # Execute command
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

Whatever you give to system has to be appropriate for the thing that will handle the command. The comments to the original question should be turned into an answer.

The system docs point to exec , which also says:

When the arguments get executed via the system shell, results are subject to its quirks and capabilities. See " STRING " in perlop for details.

This also points to the entry in perlop for backticks:

How that string gets evaluated is entirely subject to the command interpreter on your system. On most platforms, you will have to protect shell metacharacters if you want them treated literally. This is in practice difficult to do, as it's unclear how to escape which characters.

Perl doesn't address individual systems here because it supports so many of them (even when everyone who used those have disappeared).


You posted a wall of text there, and I had to rewrite it to see what you were doing. Instead of repeating the same code, a subroutine (with some reasonable formatting) is polite to the reader:)

my @commands = (
    'type \Test\hello.txt',
    q("type \Test\hello.txt")
    'type \Test\10hello.txt',
    );

foreach my $command ( @commands ) {
    try_it( $command );
    }

sub try_it  {
    my( $cmd ) = @_;
    system('ECHO '.$cmd); 
    system($cmd) == 0               # Execute command
      or die qq(system("$cmd") failed: $?!) ;
    if ($? == -1) {
        print qq(system("$cmd") failed to execute: $!!\n);
        }
    elsif ($? & 127) {
        printf qq(system("$cmd") child died with signal %d, %s coredump\n),
            ($? & 127),  ($? & 128) ? 'with' : 'without' ; 
        }
    elsif ($? != 0) {
        printf qq(system("$cmd") child exited with value %d\n), $? ; 
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM