Escaping the and (&) sign in Powershell

I need to use \r\n inside of ffmpeg --header parameter. This works in Unix, but not in Windows command prompt. So I was wondering to use powershell

powershell c:\ffmpeg -headers 'User-Agent: user-agent'"`r`n"'Cookies: my-cookie' ...

I understand I have to use 'string' when special characters are used and

"`r`n"

as my \r\n delimiter.

I have also tested that I can mix them together, like 'this '"is "'text' to get this is text

However if my string (cookie or user-agent) contains & character, it fails.

Example: powershell c:\ffmpeg -headers 'Cookies: param=a=1&b=2; session=123'

How can I "escape" & character in one-liner?


These examples (some parts are masked) are accepted by CMD, but they are not working

powershell -c "c:\ffplay -user_agent ""Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0"" -headers ""Cookie: nlqptid=h=676886edeea5bae904b0cf53daec8038.1519940538670&hdnea=exp=1519940598~acl=/*~hmac=C0E019502B060D23AB02BB157FCFFC72404500770A2CE5B00789A84AAEFBD77F&nltid=xxxxxxxxxx&nltdt=0&uid=744826&csid=xxxxxxxxxx; hdntl=exp=1520026938~acl=%2f*~hmac=952689e6de57a2a201ddc1d4c0794962fdc886ea48cf41494a42e787ef923bf9`r`n"" -i ""https://xxxxxxxxxx.net/nlds_vod/xxxxxxxxxx/vod/2018/02/28/cd264e10-dd54-3de2-df90-4c1cac104dcb/v1/stream/cd264e10-dd54-3de2-df90-4c1cac104dcb_1_4500_pc.mp4.m3u8"""

or

powershell -c "c:\ffplay -headers ""User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0`r`nCookie: nlqptid=h=676886edeea5bae904b0cf53daec8038.1519940538670&hdnea=exp=1519940598~acl=/*~hmac=C0E019502B060D23AB02BB157FCFFC72404500770A2CE5B00789A84AAEFBD77F&nltid=xxxxxxxxxx&nltdt=0&uid=744826&csid=xxxxxxxxxx; hdntl=exp=1520026938~acl=%2f*~hmac=952689e6de57a2a201ddc1d4c0794962fdc886ea48cf41494a42e787ef923bf9`r`n"" -i ""https://xxxxxxxxxx.net/nlds_vod/xxxxxxxxxx/vod/2018/02/28/cd264e10-dd54-3de2-df90-4c1cac104dcb/v1/stream/cd264e10-dd54-3de2-df90-4c1cac104dcb_1_4500_pc.mp4.m3u8"""

ffplay says

An input file must be specified

But the input file is specified after -i parameter.

What is wrong with this command?


Note that the implementation is a part of the existing batch script, therefore it is required to use a syntax working inside of batch file.


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\"' "
    

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.