tl;dr
On PowerShell's command line only, use \" to pass a " through to the code that -c (-Command) should execute.
Only in the resulting code does PowerShell's usual escaping of " as `" apply, so you may have to combine the two escaping techniques: `\".
- Your attempt,
`"", had the same effect, but it doesn't work reliably.[1]
\" works robustly with respect to PowerShell's own parsing of its command line, but can situationally break calls on the cmd.exe side - see the bottom section for workarounds.
When calling CLIs (external console applications) from PowerShell, not only do PowerShell's own, different quoting rules apply first (support for '...' strings, embedded " inside "..." escaped as `"), a long-standing bug up to PowerShell 7.2.x additionally requires escaping " chars. with \ when embedded in external-program arguments (only); see this answer.
this feature is named PSNativeCommandArgumentPassing
No; this feature - which became official in PowerShell 7.3 (see this answer) - does not come into play, because:
it generally isn't (and won't be) available in the legacy Windows PowerShell edition that you're invoking via its CLI, powershell.exe (whereas the modern, cross-platform PowerShell (Core) edition's CLI is pwsh.exe)
it only applies to calls from inside a PowerShell session.
it is designed to address a long-standing problem when calling external programs with embedded " or empty-string string arguments from PowerShell - see this answer.
Therefore, the linked answer addresses your last question:
-
Also, what are the equivalent commands when calling PowerShell from powershell.exe, rather than cmd.exe?
In short: unfortunately, up to at least PowerShell 7.2.x you'll have to additionally, manually escape " chars. with " embedded in external-program arguments (only).
Why the following works from cmd.exe:
powershell -c "echo \"That's a single quote: ' \""
PowerShell only recognizes \ as an escape character on its command line, for consistency with other CLIs.
Inside a PowerShell session, only ` (backtick) serves as the escape character.
Caveat: While \" to escape " works consistently in both PowerShell editions on the PowerShell (command-line parsing) side, situationally it can break cmd.exe's own parsing - see the bottom section.
When the PowerShell CLI is invoke via -c (-Command) with a piece of PowerShell source code to execute, that code (the argument(s) following -c is parsed in two stages:
- First, all unescaped
" chars. are stripped, wheres escaped ones (\") are kept and unescaped.
- Only then is the result parsed and execute as PowerShell code.
Therefore, what PowerShell ends up executing is verbatim:
echo "That's a single quote: ' "
From the above follows why this does not work:
:: SYNTAX ERROR
powershell -c "echo \"That's a double quote: \\\" \""
PowerShell ends up trying to execute verbatim
echo "That's a double quote: \" "
which is a syntax error, because inside a PowerShell session \ doesn't escape " -only `" or - inside "...", alternatively - "" do.
From the above follows why this (mostly) works:
:: Works, but not robustly
powershell -nop -c "echo \"That's a double-quote: `"" \""
"" sometimes, but not always works as an alternative to \";[1] here it does - see also the bottom section.
As a result, PowerShell ends up executing the following verbatim, which works, because the escaped " that was passed through is now `-escaped, as it needs to be inside a PowerShell "..." string:
echo "That's a double-quote: `" "
To avoid the brittle "" escaping, it is better to formulate this command by combining the required `-escaping with the command-line \-escaping - i.e. `\" - but see the bottom section for a fully robust solution:
powershell -nop -c "echo \"That's a double-quote: `\" \""
Avoiding parsing problems on the cmd.exe side, a safe alternative to \":
While \" to escape " works consistently in both PowerShell editions on the PowerShell (command-line parsing) side, situationally it can break cmd.exe's own parsing. By contrast, using \" is safe when calling from no-shell environments such as Task Scheduler.
While there are workarounds, they are, unfortunately PowerShell edition-specific:
Important:
These workarounds require that the whole code to pass to -c (-Command) be passed as a single, "..."-enclosed argument.
-c (-Command) also accepts multiple arguments - which may individually be double-quoted or not - in which case it simply concatenates these arguments, after having stripped unescaped ", to form the code to execute. This technique situationally allows you to get away with \"-escaping (e.g., powershell -c \"Between 2 & 3`\"\", but (a) it requires you to pay close attention to which parts of the command cmd.exe will see as unquoted, (b) would require you to ^-escape any cmd.exe metacharacters such as & in those parts, and (c) invariably performs whitespace normalization, i.e. folds runs of multiple spaces into a single one each.
The following calls, designed to print verbatim Between 2 & 3" , demonstrate this:
:: BREAKS, because cmd.exe sees `&` as *outside a double-quoted string*
powershell -c " \" Between 2 & 3`\" \" "
:: PowerShell (Core) workaround
pwsh -c " "" Between 2 & 3`"" "" "
:: Windows PowerShell workaround
powershell -c " "^"" Between 2 & 3`"^"" "^"" "
[1] An example of where "" inside "..." doesn't work is powershell -c "echo \" Nat `""King`"" Cole \"": instead of Nat "King" Cole, it prints Nat "King Cole, i.e. the second escaped " is missing (it would work fine in pwsh.exe, however, as discussed in the bottom section). It's ultimately not worth speculating how, precisely, embedded "" sequences are parsed by powershell.exe -c, given that it demonstrably isn't reliable and that reliable alternatives do exist (\" or, from cmd.exe, also "^"").