I'm trying to escape some calls in bat file and I found out that I don't understand even on simple example the weird handling of double quotes:
Try
cmd /c "echo " "%TEMP%" rem this gives: " "C:\Users\xyz\AppData\Local\Temp
cmd /c "echo" "%TEMP%" rem this gives: The filename, directory name, or volume label syntax is incorrect.
cmd /c "echo beg "TEMP" %TEMP%" rem this gives: beg "TEMP" C:\Users\xyz\AppData\Local\Temp
cmd /c "echo beg ^"TEMP^" %TEMP%" rem this gives: beg "TEMP" C:\Users\xyz\AppData\Local\Temp
cmd /c "echo beg \"TEMP\" %TEMP%" rem this gives: beg \"TEMP\" C:\Users\xyz\AppData\Local\Temp
Just open command prompt (cmd.exe) and paste code. The results are the same when copy/paste to cmd.exe or running a bat file.
What I would expect is that cmd /c "echo beg \"TEMP\" %TEMP%"
should work correcctly. At least according to http://daviddeley.com/autohotkey/parameters/parameters.htm#WIN .
But I don't understand output from all the samples. Anybody could explain me that behaviour?
Edit :
The site I'm referencing just explains how arguments are parsed on Windows. Eg http://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES
What is my expected output? I just want to know how that passing of double quotes work. Later I'd like to construct command lines like this one:
pwsh -noprofile -command "produceSomeStringsToFind | % { rg -g testfile* \" $_ some string that ends with quote\\\"" . }"
where rg
is https://github.com/BurntSushi/ripgrep - where the \" $_ some string that ends with quote\\\""
part is regular expression where I need to escape the quotes.
From the help text 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 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. [...]
It becomes clear that you are facing the situation explained in section 2.
, because echo
is not an executable file but an internal command. So if the first character is a "
, it becomes removed and so becomes the last "
, and all the other characters are preserved.
Now let us go through your command lines. So after being parsed and processed by cmd /c
:
cmd /c "echo " "%TEMP%"
becomes echo " "C:\Users\xyz\AppData\Local\Temp
. cmd /c "echo" "%TEMP%"
becomes echo" "C:\Users\xyz\AppData\Local\Temp
; then the command echo"
is tried to be executed, but which is not a valid one, hence it fails.cmd /c "echo beg "TEMP" %TEMP%"
becomes echo beg "TEMP" C:\Users\xyz\AppData\Local\Temp
. cmd /c "echo beg ^"TEMP^" %TEMP%"
becomes echo beg "TEMP" C:\Users\xyz\AppData\Local\Temp
, because escaping with ^
happens even before cmd /c
is executed, so it receives the already escaped literal "
characters. cmd /c "echo beg \"TEMP\" %TEMP%"
becomes echo beg \"TEMP\" C:\Users\xyz\AppData\Local\Temp
, because the \
is nothing special to cmd
. If you want to output the text "%TEMP%"
(including the quotes), yo could do this:
rem // This preserves all quotes, because the first character is not such:
cmd /c echo "%TEMP%"
rem // This removes the outer-most pair of quotes, because the first character is such:
cmd /c "echo "%TEMP%""
rem /* This removes the outer-most pair of quotes too, since `cmd /c` receives the already
rem escaped `"`; however, this could be useful to hide these quotes from the hosting
rem `cmd` instance, which avoids issues when `%TEMP%` contains special characters
rem (like `&` or `^`), which you would otherwise have to individually escape: */
cmd /c ^"echo "%TEMP%"^"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.