11

I see that the caret is the documented escape character.

But, I have an example showing that for the double quote character, ^ doesn't work and you have to use \

C:\>runas /user:Administrator "cmd /k dir \"%userprofile%\""

Why is that, and where is it documented?

3 Answers 3

6

One of the examples in RUNAS /? shows that syntax. The caret is the escape character for CMD.EXE but in Windows individual programs are free to implement their own escape characters and globbing.

4
  • interesting.. and btw.. what is cmd.exe doing with the unescaped quotes at the end? does it keep them, if so why.. Or does it remove them.. if so, why were they needed in the first place?
    – barlop
    Aug 30, 2010 at 10:22
  • @barlop: See Michael's answer. Aug 30, 2010 at 14:45
  • 1
    are you sure \" is being interpreted by runas and not by cmd.exe? compiling this w.c pastebin.com/28Q2Wxxr to w.exe Compare a)w "a a" b)w \"a a\" c)w ^"a a^" Notice what happens with b in particular. I guess that's the cmd shell treating \ as an escape character.
    – barlop
    Sep 13, 2011 at 7:13
  • while it hasn't been cmd.exe that interpreted it, it's not the program either, it's the runtime that split args. i'm not sure if one would call that the program being free to implement it. more like the way the compiler implemented it, or the way the compiler implements it for the programs. any programs written in i suppose, ms visual c, would parse argsv "thusly" msdn.microsoft.com/en-us/library/a1y7w461.aspx
    – barlop
    Aug 28, 2013 at 18:07
17

In cmd, \ does not escape ". Here's a quick proof and explanation:

  1. Run echo "" & echo 1. (& is a special char in cmd, left & right means run left then run right.) We can see that both echo "" and echo 1 are run successfully.

  2. Next, run echo " & 1234. We can see that the output is " & 1234. This is because the opening " has not been closed, and thus everything after it is interpreted as a string, including the special char &.

  3. Run echo "\" & 1234.

    • If \ does escape the following ", the opening " will not be closed and the chars & 1234 will be interpreted as part of the string.

    • If \ fails to escape the following ", that following " will close the string and & 1234 will not be interpreted as part of the string.

    In the output, we do not see & 1234 interpreted as part of the string. This proves that \ has failed to escape ".

So what escapes " within quotes for argument passing? While ^ will work outside of quotes (easily proven via echo ^" & echo 1), it does not escape quotes within quotes.

Indeed, how can we get something as simple as echo """ & echo 1 to work?

The ^ char? ...Nope, echo "^"" & echo 1 outputs "^"", and not """.

What about the " char itself? ...Nope, echo """" & echo 1 outputs """", and not """.

The fact is, there's nothing that will escape " within quotes for argument passing. You can brood over this for a couple of years and arrive at no solution. This is just some of the inherent limitations of cmd scripting.

However, the good news is that you'll most likely never come across a situation whereby you need to do so. Sure, there's no way to get echo """ & echo 1 to work, but that's not such a big deal because it's simply a contrived problem which you'll likely never encounter.

For example, consider runas. It works fine without needing to escape " within quotes because runas knew that there's no way to do so and made internal adjustments to work around it. runas invented its own parsing rules (runas /flag "anything even including quotes") and does not interpret cmd arguments the usual way. Official documentation for these special syntax is pretty sparse (or non-existent). Aside from /? and help, it's mostly trial-and-error.

1
  • Quick testing, echo ^"^"^" & echo 1 works. In wine cmd at least.
    – user202729
    Aug 8, 2022 at 16:31
3

The \ sign makes the interpreter interpret the next sign as a character instead of an identifier.

You see it a lot in code as well:

"Hello \"World\""

this is interpreted as

Hello "World"

in your example, in order to pass the arguments to cmd, it needs to be enclosed in "". But since the arguments to cmd contains " (and this would end the enclosure) they are appended by \. If the "" would not have been there, the /k dir \"%userprofile%\" would have been interpreted as arguments to runas, not to cmd.

The reason why they are enclosing the %userprofile% is because this is an environmental variable and will be replaced by text which could contain spaces, which (for the same reason as above) would make the argument to cmd incorrect.

16
  • Looks to me like RunAs "needs" quotes when that second parameter, the program parameter, has a space. Otherwise it thinks it is being given more parameters than it is. In theory, runas could have been written(I mean coded) to take it to the end, as one parameter no quotes necessary. In contrast to this. cmd.exe e.g. cmd /c dir a b That takes -dir a b- as one parameter.
    – barlop
    Aug 30, 2010 at 23:46
  • Also, a more complex point, it looks to me like runas could've done without \" But can't because it is taking the " as start and the next " as end. If it just took the outter-most ones as beginning and end, then it wouldn't need middle ones to be \" e.g. even a nasty looking line like this C:\>runas /user:Administrator "runas /user:Administrator \"cmd /k dir \"%userprofile%\"\" " If it were all " and no \" then theoretically you can still process it. But not so because of the way runas has been written.
    – barlop
    Aug 30, 2010 at 23:50
  • @barlop: Don't think of cmd as the argument to runas, because it is not. The argument to runas is cmd /k dir \"%userprofile%\". I don't have the time now, but give me a couple of hours and I should be able to explain a simple C++ program to you and how those programs interpret arguments. I think it would be more clear. So, answer bound to change
    – default
    Aug 31, 2010 at 7:36
  • Actually I may understand and just wasn't clear. I'm aware of the main method and argsv. I heard that they take all arguments in their first element? is that right? Regarding me mentioning cmd.exe, there is an ambiguity whether I mean cmd.exe in that line, or the outter cmd.exe that the line is written in. The only time I mentioned cmd.exe in what I wrote in these comments, was cmd /c dir a b And i'm right that -dir a b- is 1 parameter. But I have been told(don't know if correctly) that all windows programs get all their args as 1 string, presumably argsv[0],then split it themselves
    – barlop
    Aug 31, 2010 at 9:22
  • 1
    @Michael, if you want it in Why form.. I could ask. Why is cmd /c dir a b interpreted like cmd /c "dir a b" Whereas with runas, the program parameter(See runas /?) wants quotes. I think runas could've easily been coded to not want them. Since looks to me like theoretically it shouldn't need them.
    – barlop
    Aug 31, 2010 at 18:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .