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
)[1] (which is powershell.exe
's default parameter):
If possible, use \"...\"
, the preferred form of escaping, because it works in both PowerShell editions and also aligns with how most CLIs expect "
to be escaped; however, it doesn't work in all cases when calling from cmd.exe
, such as the case at hand.
By contrast, \"...\"
is always safe to use from no-shell contexts, such as Task Scheduler and the Windows Run
dialog (WinKey-R).
To also handle all edge cases of calling the PowerShell CLI from cmd.exe
/ batch files - namely when the string to be quoted contains cmd.exe
metacharacters such as |
or &
(as in your case) - use the following in lieu of \"...\"
, again inside overall "..."
quoting:
When calling Windows PowerShell (powershell.exe
): use \""...\""
(sic), as shown above.
"^""..."^""
(sic) and, in for /f
loops, " ^^^"\"...\""
(sic) - see the bottom section of this answer.When calling PowerShell (Core) 7 (pwsh.exe
): use ""...""
, which is fully robust (prevents both misinterpretation by cmd.exe
and whitespace normalization).
As an aside: As a general requirement, %
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\"' "
\"
by individually ^
-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.
[1] Using overall "..."
quoting around what then becomes a single -Command
argument is conceptually preferable, but not strictly necessary. If overall "..."
quoting is not used, \"
-escaping of "
characters that are to be treated as part of the command is the only supported form - see this answer.