Escaping the and (&) sign in Powershell

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 from cmd.exe, notably in the case at hand, due to the string to be quoted containing cmd.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 that cmd.exe itself interprets ... as being inside a double-quoted string, which is what makes these escaping forms robust.

  • If \"...\" were used inside "..." from cmd.exe (which only recognizes "" as an escaped "), it would in effect see ... as being outside a double-quoted string, which would cause values that contain cmd.exe metacharacters such as & and | to break the command. Compare the following invocations from cmd.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 such cmd.exe characters (e.g., ^&), but that requires you to analyze the string carefully and determine which specific parts cmd.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.

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.

Leave a Comment