The 2nd document quoted by Peter Mortensen in his comment on the answer of Codesmith made things much clearer for me. That document was written by windowsinspired.com. The link repeated: A Better Way To Understand Quoting and Escaping of Windows Command Line Arguments.
Some further trial and error leads to the following guideline:
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.
If you want your program foo to receive the command line text "a\"b c" > d
and redirect its output to file out.txt, then start your program as follows from the Windows command shell:
foo ^"a\^"b c^" ^> d > out.txt
If foo interprets \"
as a literal double quote and expects unescaped double quotes to delimit arguments that include whitespace, then foo interprets the command as specifying one argument a"b c
, one argument >
, and one argument d
.
If instead foo interprets a doubled double quote ""
as a literal double quote, then start your program as
foo ^"a^"^"b c^" ^> d > out.txt
The key insight from the quoted document is that, to the Windows command shell, an unescaped double quote triggers switching between two possible states.
Some further trial and error implies that in the initial state, redirection (to a file or pipe) is recognized and a caret ^
escapes a double quote and the caret is removed from the input. In the other state, redirection is not recognized and a caret does not escape a double quote and isn't removed. Let's refer to these states as 'outside' and 'inside', respectively.
If you want to redirect the output of your command, then the command shell must be in the outside state when it reaches the redirection, so there must be an even number of unescaped (by caret) double quotes preceding the redirection. foo "a\"b " > out.txt
won't work -- the command shell passes the entire "a\"b " > out.txt
to foo as its combined command line arguments, instead of passing only "a\"b "
and redirecting the output to out.txt.
foo "a\^"b " > out.txt
won't work, either, because the caret ^
is encountered in the inside state where it is an ordinary character and not an escape character, so "a\^"b " > out.txt
gets passed to foo.
The only way that (hopefully) always works is to keep the command shell always in the outside state, because then redirection works.
If you don't need redirection (or other characters with special meaning to the command shell), then you can do without the carets. If foo interprets \"
as a literal double quote, then you can call it as
foo "a\"b c"
Then foo receives "a\"b c"
as its combined arguments text and can interpret it as a single argument equal to a"b c
.
Now -- finally -- to the original question. myscript '"test"'
called from the Windows command shell passes '"test"'
to myscript. Apparently myscript interprets the single and double quotes as argument delimiters and removes them. You need to figure out what myscript accepts as a literal double quote and then specify that in your command, using ^
to escape any characters that have special meaning to the Windows command shell. Given that myscript
is also available on Unix, perhaps \"
does the trick. Try
myscript \^"test\^"
or, if you don't need redirection,
myscript \"test\"