When calling from cmd.exe
, things get tricky; here’s a simplified example:
powershell -c "ffmpeg.exe -h "^""User-Agent: usra`r`nCookies: parm=a=1&b=2; session=1"^"""
In short: From cmd.exe
/ batch files, to pass what PowerShell’s CLI should see as a double-quoted argument inside an overall "..."
string passed to -Command
(-c
):
-
In Windows PowerShell (
powershell.exe
): use"^""..."^""
(sic) -
In PowerShell (Core) v6+ (
pwsh.exe
): use""...""
-
Note:
-
While
\"...\"
works in both PowerShell editions, it doesn’t work robustly when called fromcmd.exe
, notably in the case at hand, due to the string to be quoted containingcmd.exe
metacharacters such as&
– see below. -
However, from no-shell contexts, such as Task Scheduler and the Windows
Run
dialog (WinKey-R),\"...\"
works robustly and may be preferable due to being edition-agnostic, as well as being aligned with how most CLIs expect"
chars. to be escaped.
-
As a general requirement, literal %
chars. must be escaped as %%
to prevent them from being interpreted as part of a cmd.exe
variable reference in batch files. From the command prompt, things are unfortunately more complicated.
-
The command line for PowerShell is best passed as a single,
"..."
-enclosed string, via parameter-c
(short for-Command
, which in Windows PowerShell is the default, but that has changed in PowerShell (Core) v6+, which now defaults to-File
). -
Since the PowerShell CLI strips unescaped
"
characters during command-line parsing, before interpreting the result as PowerShell code, any"
instances to be retained as part of the command to ultimately execute must be escaped (note that PowerShell-internally`"
is used to escape a"
; alternatively, in the context of"..."
strings only,""
may be used). -
"^""..."^""
(Windows PowerShell) and""...""
(PowerShell (Core) v6+) inside an overall"..."
-c
argument ensure thatcmd.exe
itself interprets...
as being inside a double-quoted string, which is what makes these escaping forms robust. -
If
\"...\"
were used inside"..."
fromcmd.exe
(which only recognizes""
as an escaped"
), it would in effect see...
as being outside a double-quoted string, which would cause values that containcmd.exe
metacharacters such as&
and|
to break the command. Compare the following invocations fromcmd.exe
:# OK - prints verbatim: The king of "Rock & Roll" C:\>powershell.exe -c " 'The king of "^""Rock & Roll"^""' " C:\>pwsh.exe -c " 'The king of ""Rock & Roll""' " # !! BROKEN - cmd.exe interprets "&" as a metachar. C:\>powershell.exe -c " 'The king of \"Rock & Roll\"' " C:\>pwsh.exe -c " 'The king of \"Rock & Roll\"' "
- Note: You could fix the use of
\"
by^
-escaping suchcmd.exe
characters (e.g.,^&
), but that requires you to analyze the string carefully and determine which specific partscmd.exe
sees as unquoted. If you make a mistake, the^
will be retained as a literal part of the string. The advantage of the"^""
/""
approach is that you needn’t worry about such pitfalls.
- Note: You could fix the use of
As an aside: 'this '"is "'text'
does not create a single string the way it does in Bash; in PowerShell:
-
As a stand-alone expression, it causes a syntax error (try executing it by itself); you’d have to use
('this ' + "is " + 'text')
or use a single quoted string ('this is text'
). -
As an argument passed to a command (program), it is interpreted as 3 distinct arguments – see this answer for an explanation of this – surprising – behavior.