and let the underlying shell do the work?
PowerShell is a shell, so there is no underlying shell as such (in the sense that PowerShell needn't be launched from another shell).
However, there are platform-specific default shells: cmd.exe
on Windows, and /bin/sh
on Unix-like platforms.
I need to call a command, that I copy from a site or other
Before PowerShell went cross-platform, --%
, the stop-parsing token was introduced in Windows PowerShell v3, precisely to address your scenario.
Given that Windows was the only supported platform at the time, the behavior is focused on cmd.exe
- and even there it doesn't support cmd.exe
's line continuation via line-ending ^
chars.
More generally, while it tries to emulate cmd.exe
's behavior (e.g., by expanding %
-enclosed tokens such as %USERNAME%
as environment-variable references) without actually delegating to the latter, it doesn't do so fully.
In PowerShell Core (v6+) --%
is even supported on Unix-like platforms, but is of little utility there, given that cmd.exe
semantics are applied even there; notably, '...'
-quoting is not supported.
(Note that PowerShell emulates one /bin/sh
feature on Unix-like platforms, but only without use of
--%
: globbing, i.e. the expansion of unquoted tokens such as *.txt
to matching file paths).
However, you can call the platform-native shell explicitly, e.g, by passing the copied command string to sh -c
on Unix-like platforms, using a (verbatim) here-string for the command string:
# Call the platform-native shell with a command crafted for it:
sh -c @'
echo This line\
keeps going\
with --all-namespaces and\
with -o custom-columns='KIND:kind,NAMESPACE'
'@
Unfortunately, there's a catch:
Up to at least v7.2.x, PowerShell's handling of embedded "
chars. in arguments passed to external programs (such as sh
) is fundamentally broken, requiring embedded "
to be manually \
-escaped:
# !! BROKEN
sh -c @'
echo "high noon"
'@
To make this work, you have to \
-escape manually:
# WORKAROUND
sh -c (@'
echo "high noon"
'@ -replace '"', '\"')
See this answer and this GitHub issue for background information.
In short: Backward-compatibility concerns prevent fixing the default behavior, but discussions are underway to at least allow opting into sane default behavior.