Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I deal with quote characters when using cmd.exe

I'm trying to do this:

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

However, I have problems which are down to the way cmd.exe works. If you read the help for it, it handles " characters in a special way. See the help at the end of question. So, this doesn't execute correctly... I'm guessing cmd.exe strips some quotes which makes the statement ill-formed.

I can do this successfully:

// quotes not required around folder with no spaces cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > C:\temp\FolderWithNoSpaces\SomeProgram.out 

But, I really need the first one to work. Is there away around the strange quote processing that cmd.exe uses? I want it to preserve all of the quotes, but there doesn't appear to be an option to make it do that.


Help taken from output of: 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:      - 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       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, preserving     any text after the last quote character. 
like image 569
Scott Langham Avatar asked Dec 10 '08 13:12

Scott Langham


People also ask

How do you escape quotes in cmd?

Escape every double quote " with a caret ^ . If you want other characters with special meaning to the Windows command shell (e.g., < , > , | , & ) to be interpreted as regular characters instead, then escape them with a caret, too.

How do I escape special characters in cmd?

If you need to use any of these characters as part of a command-line argument to be given to a program (for example, to have the find command search for the character >), you need to escape the character by placing a caret (^) symbol before it.

How do I use special characters in cmd?

In Windows, you can type any character you want by holding down the ALT key, typing a sequence of numbers, then releasing the ALT key.

How do you use quotation marks in cmd?

Generally, to differentiate commands from other types of instructions, enclose the command within single or double quotation marks. When issuing TSO/E commands in an exec, it is recommended that you enclose them in double quotation marks.


2 Answers

Ah. doh. Think I've answered my own question.

If you use /S, and wrap the whole thing in quotes, it just removes those outer quotes.

cmd.exe /S /C " do what you like here, quotes within the outermost quotes will be preserved " 
like image 139
Scott Langham Avatar answered Oct 03 '22 10:10

Scott Langham


I think you'll find that your example works absolutely fine as it is.

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

I have reproduced your example here http://pastebin.com/raw.php?i=YtwQXTGN

C:\>cmd /c "c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\a.a"  C:\>type "c:\temp\spaces are here\a.a" my long program.exe has run  C:\>  further example demonstrating it works with "my long program.exe", removing cmd /c, it operates fine too.  C:\>"c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\ a.a"  C:\>type "c:\temp\spaces are here\a.a" my long program.exe has run  C:\>    Another example, but with replace.  replace with no parameters says "source path required"  "no files replaced"  C:\>replace > a.a Source path required  C:\>type a.a No files replaced  Exactly the same effect when they're in folders with spaces.  C:\>cmd /c "c:\Program Files\my folder\replace.exe" > "c:\temp\spaces are here\r.r" Source path required  C:\>type "c:\temp\spaces are here\r.r" No files replaced  C:\>  further demonstration with replace without cmd /c works fine too.  C:\>"c:\Program Files\my folder\replace.exe" > "c:\temp\spaces are here\r.r" Source path required  C:\>type "c:\temp\spaces are here\r.r" No files replaced  C:\> 

The reason why your example works fine

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

and how/why it works the way it does, is because the > is interpreted as special by the host.exe So this part cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" - I think - is evaluated first. i.e. cmd /c does not see the > and after.

cmd /? shows 2 cases

Case 1 and Case 2. Your example fits Case 1

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:          - 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, preserving         any text after the last quote character. 

You can test for sure that your example fits case 1, because if you add /s (without adding any more quotes or making any change at all to your example other than adding /s), then you get a different result, because it makes your example hit case 2. So that proves that your example is definitely a case 1. And it clearly meets all the criteria of case 1. If your example were a case 2, and you added /s, then it'd make no difference.

Your answer is interesting because it shows an alternative way of getting your result, but in case 2. By adding additional outter quotes and adding /s.

But actually, when you add those additional outter quotes, then you've just made it a case 2, and adding a /s on top of that won't make a difference.

C:\>cmd /c "c:\Program Files\my folder\replace.exe" Source path required No files replaced  C:\>cmd /s /c "c:\Program Files\my folder\replace.exe" 'c:\Program' is not recognized as an internal or external command, operable program or batch file.  C:\>cmd /c ""c:\Program Files\my folder\replace.exe"" Source path required No files replaced  C:\>cmd /s /c ""c:\Program Files\my folder\replace.exe"" Source path required No files replaced  C:\> 

The example in your question worked fine

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

Your alternative (with the /S and outer quotes) you give as an answer to make the example work, works fine too

cmd.exe /S /C ""C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"" 

Though your answer which is an alternative, can actually be simplified by removing the /S because it's already a case 2, so adding /s won't make any difference. So this would improve the solution given in your answer

cmd.exe /C ""C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"" 

Your example which you described as a problem in your question, and your solution, produce the same good result. But one big difference I suppose, (and I am not sure how to test for it), but one difference in the way your example works, and the way the solution in your answer works, is I think in the case of your example, the hosting/invoking cmd.exe does the redirect to the file. Whereas in your solution's example, the invoked cmd.exe is passed the > by the host cmd.exe, and so the invoked cmd.exe does the redirect. Also of course, your example is a case 1, while your solution is an amendment you made (very well) to make it work in case 2.

I hope I haven't erred here, I may have. But your question and answer did help me wrap my head around how cmd and in particular cmd /c is working!

Perhaps your example was an oversimplification of your actual one, and your actual one did fail and needed your amendment. If your example case, had been a tiny bit more complex, by for example, having a parameter to the program that took quotes, then it'd fail Case 1, and you would indeed need outter quotes (/S would not change the result, so no /S would be necessary, as it'd already be a case 2 once you add those needed outer quotes). But the example you gave in your question actually seems to me to work fine.

Added - A related Q and A What is `cmd /s` for?

like image 28
barlop Avatar answered Oct 03 '22 11:10

barlop