To add an explanation to Theo's effective solution:
# Use of "..." around the entire argument is the key.
# (The extra space before and after the command is just for visual clarity.)
powershell.exe " echo 'a c' "
# Alternative with embedded double-quoting
powershell.exe " echo \"a c\" "
That is, enclosing the entire command in "..." is necessary to avoid the whitespace normalization you saw.
When you pass a command (piece of PowerShell code) to the PowerShell CLI, via the -Command (-c) parameter (which is positionally implied in your case), PowerShell performs the following command-line parsing first, by splitting the command line into:
- white-space separated tokens
- with double-quoted tokens (
"...") getting recognized as single tokens even if they contain spaces, with the interior spaces getting preserved as-is; note that these (unescaped) " are removed in the process).
- Note: By contrast,
'...'-enclosed tokens are not recognized as single tokens on the command line (even though inside a PowerShell session they are), so that 'a b' is split into verbatim 'a and b'.
The resulting tokens are then joined with a single space to form the single string that is then interpreted and executed as PowerShell code.
It is during the splitting by whitespace - which can be any number of spaces between tokens - that the information about how many spaces there were between tokens is lost.
Only inside "..."-enclosed tokens is the whitespace preserved as-is, hence the use of "..." around the entire command above.
If you need to use " quoting as part of the PowerShell command (to use string interpolation), " characters must be escaped as \", as shown in the second command at the top.
However, if you're calling from cmd.exe / a batch file, this may break due to how cmd.exe parses command lines. In such edge cases, use the workarounds discussed in this answer.
powershell.exe "echo 'a c'"