my @cmd = "/cygdrive/c/Program Files/Microsoft Visual Studio .NET 2003 +/Common7/IDE/devenv.exe"; system(@cmd) and die $!;
Run this code, and it dies for no apparent reason (assuming you've installed VisualStudio in the default location). The reason it dies is the rules that system uses for calling out to the shell:
  1. if @_ > 1 then call execve
  2. if there are meta characters, then use "system -c $_[0]"
  3. otherwise, use split(" ", $_[0]) and send the resulting list to execve.
This fails when you pass a single command with no args, and that command has spaces in it (rather, it fails if you had expected the behavior of the command with args to be the same as when the command has no args). Because @_==1, and the command contains no meta characters, Perl will split the command using the spaces in the command-name, and then call execve with this list. It is not suprising that this fails. The cure is to wrap the core system command with code that handles this corner case.
use subs 'system'; sub system { if ((@_ == 1) && ($_[0] =~ /(\S*)\s/) && (! -x $1) && (-x $_[0])) { $_[0] = "'$_[0]'"; } CORE::system @_; } my @cmd = "/cygdrive/c/Program Files/Microsoft Visual Studio .NET 2003 +/Common7/IDE/devenv.exe"; system(@cmd) and die $!;

Replies are listed 'Best First'.
Re: system commands with spaces
by PodMaster (Abbot) on Apr 09, 2004 at 02:40 UTC
    Hi :) The cure is in the manual for exec
    @args = ( "echo surprise" ); exec @args; # subject to shell escapes # if @args == 1 exec { $args[0] } @args; # safe even with one-arg list
    system { $args[0] } @args; is not subject to shell escapes. Cheers

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Yes, that's probably a better implementation than quoting $_[0]. But the idea of wrapping the system() call to make it DWIM still seems like a win. The concept of the system interface is that you can call it with either a list or a scalar and it will do the right thing. Having to use a different syntax for the special case of a 1-item list (with spaces) doesn't feel right -- especially when its a simple hack to have perl figure this out for me.