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