Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

doublequoted commands inside backticks on windows, perl 5.6

by emgrasso (Novice)
on Oct 28, 2004 at 17:06 UTC ( [id://403444] : perlquestion . print w/replies, xml ) Need Help??

emgrasso has asked for the wisdom of the Perl Monks concerning the following question:

On perl 5.6 I have found that a command sequence like
$cmd="\"C:\\path\\cleartool\" -fmt \"%[owner]p\" vob:."; `$cmd`;
fails with the error message:
'C:\\path\\cleartool\" -fmt \"%[owner]p\' is not recognized as an inte +rnal or external command, operable program or batch file.
On the other hand,
$cmd="C:\\path\\cleartool -fmt \"%[owner]p\" vob:."; `$cmd`;
appears to work the same as
C:\path\cleartool -fmt "%[owner]p" vob:.
typed on the command line, which works the same as
"C:\path\cleartool" -fmt "%[owner]p" vob:.
typed on the commandline.

Is this a known problem? Is there something odd about double quotes inside backticks on windows?

Replies are listed 'Best First'.
Re: doublequoted commands inside backticks on windows, perl 5.6
by emgrasso (Novice) on Oct 28, 2004 at 18:56 UTC
    I'm still not sure why the problem is happening, but the workaround seems to be to provide an outer set of matched double quotes for Windows and Perl to munch on.
    $cmd="\"\"c:\\path\\cleartool\" -fmt \"%[owner]p\" vob:.\""; `$cmd`;
    seems to work, possibly because the double quotes that get eaten (the first and last encountered) belong to the same matched set instead of different pairs. I'd do something cleaner, like
    $cmd=qq(""c:\\path\\cleartool" -fmt "%[owner]p" vob:.");
    but I'm trying to do maintenance on some old code and get it working with the minimum changes possible. There are a lot of interpolations in the real string construction.

    This problem showed up on Windows XP, by the way. But I wouldn't be surprised if other MS Win flavors did the same thing.

Re: doublequoted commands inside backticks on windows, perl 5.6
by Fletch (Bishop) on Oct 28, 2004 at 17:25 UTC

    Use qq{} rather than "'s and you won't need as much backwhacking (not that that I have any idea about the original problem since I don't really do Win32 . . .).

Re: doublequoted commands inside backticks on windows, perl 5.6
by BrowserUk (Patriarch) on Oct 28, 2004 at 18:55 UTC

    I cannot reproduce the problem with XP/5.6.1 (AS638)?

    my $cmd = "\"c:\\perl\\bin\\perl\" -w -e\" print $] \""; print `$cmd`; 5.006001

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: doublequoted commands inside backticks on windows, perl 5.6
by jimbojones (Friar) on Oct 29, 2004 at 14:41 UTC
    Hi

    The problem is a conflict between your older version of Perl and the cmd shell used to execute backticks.

    When the backtick is used on windows, Perl constructs the command line and executes on the system with "cmd /x/c" by default (at least on builds before AS638; after, the /d flag was added. ).

    cmd has some strange quoting behaviour. From the help cmd /?

    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 is used to process quote (") characters:
    1. If all of the following conditions are met, then quote characters on the command line are preserved:
      1. no /S switch
      2. exactly two quote characters
      3. no special characters between the two quote characters, where special is one of: &<>()@^|
      4. there are one or more whitespace characters between the the two quote characters
      5. 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, preserving any text after the last quote character.
    You are seeing the effects of the second point.

    This doesn't occur in later builds of win perl, as the coders found this problem.

    from the win32.c file:

    /* The NT cmd.exe shell has the following peculiarity that needs + to be * worked around. It strips a leading and trailing dquote when +any * of the following is true: * 1. the /S switch was used * 2. there are more than two dquotes * 3. there is a special character from this set: &<>()@^| * 4. no whitespace characters within the two dquotes * 5. string between two dquotes isn't an executable file * To work around this, we always add a leading and trailing dqu +ote * to the string, if the first argument is either "cmd.exe" or " +cmd", * and there were at least two or more arguments passed to cmd.e +xe * (not including switches). * XXX the above rules (from "cmd /?") don't seem to be applied * always, making for the convolutions below :-( */
    From the 638 diff file:

    [ 12747] By: gsar on 2001/10/28 18 +:33:23 Log: finishing touches to system() fixes on windows: * detect cmd shell correctly even if it had full path i +n it * more quoting needed for single-arg system if the argu +ment really had multiple quoted arguments within it * be smarter about not calling the shell when the execu +table has spaces, but otherwise does not need shell involveme +nt * add a testsuite (windows-specific currently)
    So if you run under 5.6.1 638, as ikegami did, you get the correct behaviour. See these tests.

    test.pl. Calls another perl script to echo back the arguments, with your args

    my $cmd="\"C:\\progra~1\\accessories\\echo_arg.pl\" -fmt \"%[owner]p\ +" vob:."; print "$cmd\n"; print `$cmd`;
    Test with 5.6.1 AS635

    >perl test.pl "C:\progra~1\accessories\echo_arg.pl" -fmt "%[owner]p" vob:. C:\progra~1\accessories\echo_arg.pl -fmt %[owner]p vob:.
    Test with 5.6.0 AS623

    >C:\progra~1\perl560_623\bin\perl test.pl "C:\progra~1\accessories\echo_arg.pl" -fmt "%[owner]p" vob:. 'C:\progra~1\accessories\echo_arg.pl" -fmt "%[owner]p' is not recogni +zed as an internal or external command, operable program or batch fil +e.
    Your double-double quoting appears to be the only workaround. That is in effect what the C code does now.

    - jim

Re: doublequoted commands inside backticks on windows, perl 5.6
by ikegami (Patriarch) on Oct 28, 2004 at 17:23 UTC
    The quotes work fine for me in ActivePerl v5.6.1
Re: doublequoted commands inside backticks on windows, perl 5.6
by diotalevi (Canon) on Oct 28, 2004 at 17:12 UTC
    c:\path\cleartool\ is a directory, not a program.
      No, it is not a directory you are misreading the \" at the end of the command name:
      "c:\path\cleartool" -fmt "%[owner]p" vob:. #outside perl
      \"c:\\path\\cleartool\" -fmt \"%[owner]p\" vob:. #inside perl
      The problem is that something is eating the first quote at the beginning of the line and the second quote in the parameter section, instead of either eating matching quotes or leaving them alone.
      Then why does c:\path\cleartool -fmt "%[owner]p" vob:. work? Presumably, path is something like Program Files\cleartool

        Did you not notice that c:\path\cleartool works and c:\path\cleartool\ not? That's the difference - one ends with a backslash and the other does not. File names the end in slashes are always interpreted as directories.

Re: doublequoted commands inside backticks on windows, perl 5.6
by Anonymous Monk on Oct 28, 2004 at 18:51 UTC
    Both commands worked fine for me. Did you cut and paste the first example out of your code, or did you type it in? You may have fixed the error when you transcribed it into your post.