in reply to Re: win32 parenthesis system weirdness
in thread win32 parenthesis system weirdness

Nope, I'm not missing any spaces. But your suggestion lead me to a solution, but I'm confused why it works:
my $fn = '"C:\img\del me\three (3\00000253.jpg"'; system($fn); #Doesn't work my $fn = ' "C:\img\del me\three (3\00000253.jpg"'; system($fn); #Works
Just by adding a space after the first single quote system() suddenly works. What is the reason for this?

Replies are listed 'Best First'.
Re^3: win32 parenthesis system weirdness
by ikegami (Patriarch) on Dec 04, 2009 at 07:49 UTC

    Shell quoting is a real mess in Windows. It's basically impossible to do right programmatically. And Perl might even make it even worse in some circumstances.

    First, let's see how it doesn't work since you've kept that a secret from us:

    >perl a.pl 'C:\img\del' is not recognized as an internal or external command, operable program or batch file.

    I suspect Perl is executing the following commands:

    >cmd /c "C:\img\del me\three (3\00000253.jpg" 'C:\img\del' is not recognized as an internal or external command, operable program or batch file. >cmd /c " "C:\img\del me\three (3\00000253.jpg"" [cutest bunny ever is displayed]

    (Cutest bunny ever)

    Don't ask my why those commands are those that are run. Don't ask my why that second one even works. Cause I'm not sure I can answer.

    See Re^4: win32 parenthesis system weirdness for a solution.

Re^3: win32 parenthesis system weirdness
by BrowserUk (Patriarch) on Dec 04, 2009 at 06:46 UTC

    Dunno. It works for me with 5.8.9 & 5.10.1. If I omit the 'dir ' from my example, it loads the image into the default image viewer. No leading space required.

    Admittedly I haven't bothered to exactly replicate your weird path. Perhaps that is somehow fooling Perl's command parser into believing that the first part of the path is actually a command and is therefore bypassing the shell and failing.

    If it is a bug, it's probably too obscure to be bothered trying to fix. You have a workaround, though avoiding weird dir names might be easier :)


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Don't think using parenthesis in dirnames is that unusual ;)?! It's not just that single parenthesis at the end that causes this behavior. Paths like this also won't open without that extra space:
      my $fn = q{ C:\img\del me\pic (images)[2k]\00000253.jpg"};
      Tried with perl 5.10 also, but same behaviour:
      #works (note extra space required) "H:\TEST\ActivePerl-5.10.0.1001-MSWin32-x86-283495\perl\bin\perl.exe" +-e "my $fn = ' \"C:\img\del me\three (3\00000253.jpg\"'; system($fn)" #Doesn't work "H:\TEST\ActivePerl-5.10.0.1001-MSWin32-x86-283495\perl\bin\perl.exe" +-e "my $fn = '\"C:\img\del me\three (3\00000253.jpg\"'; system($fn)" 'C:\img\del' is not recognized as an internal or external command, operable program or batch file.
      But since this doesn't work either (as mentioned by ikegami):
      cmd.exe /c "C:\img\del me\three (3\00000253.jpg"
      Then I don't consider this whole problem to be perl related.

      What I now need to understand is why the "(" char is treated in this special way in windows and what other chars create similar weird behaviour? Didn't think "(" was spcecial "meta-char", like | or > etc, that needed to be escaped (and even escaping it with ^ also didn't work).

        '(' and ')' are special characters. They are used grouping commands like:

        >(md x && cd x) || (echo "Couldn't create x" & exit)

        The rules for how cmd.exe treats quotes (usefully provided by help cmd), are as follows:

        If /C or /K is specified, then the remainder of the command line after the switch is processed as a command line, where the following logic i +s used to process quote (") characters: 1. If all of the following conditions are met, then quote charact +ers on the command line are preserved: - no /S switch - exactly two quote characters - no special characters between the two quote characters, where special is one of: &<>()@^| - there are one or more whitespace characters between the two quote characters - the string between the two quote characters is the name of an executable file. 2. Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preservin +g any text after the last quote character. ... The special characters that require quotes are: <space> &()[]{}^=;!'+,`~

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re^3: win32 parenthesis system weirdness
by Anonymous Monk on Dec 04, 2009 at 06:20 UTC

    ETOOMUCHMAGIC :-)

Re^3: win32 parenthesis system weirdness
by Anonymous Monk on Dec 04, 2009 at 06:25 UTC
    If you want to rely on shell behaviour be explicit
    system "cmd.exe /c $fn" system "cmd.exe /c start $fn" system qw' cmd.exe /c start ', $fn;

      None of those work. See Re^3: win32 parenthesis system weirdness for why the first doesn't work.

      As for the last two, it's due to start's very wonky parameter handling. If the first non-option arg is quoted, it's taken to be the title.

      start file.jpg # Works start "file.jpg" # Doesn't work. Same as following start "file.jpg" cmd # Launches cmd in new Window titled file.jpg start "" "file" # Works
      So you want
      my $qfn = 'C:\img\del me\three (3\00000253.jpg'; system(qq{start "" "$qfn"});