2

In Powershell(pwsh) Is it possible to "bypass" Powershell to not do anything and let the underlying shell do the work?

Sometime I need to call a command, that I copy from a site or other, that includes "\" and not "ยด" for line break - or other parameters, that Powershell try to interpolate.

Like:

 <Powershell Function> kubectl get rolebindings,clusterrolebindings \                                      
  --all-namespaces  \
  -o custom-columns='KIND:kind,NAMESPACE:metadata.namespace,NAME:metadata.name,SERVICE_ACCOUNTS:subjects[?(@.kind=="ServiceAccount")].name' | grep name
Chris G.
  • 23,930
  • 48
  • 177
  • 302

2 Answers2

4

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

Not that I'm aware of. I also don't know of any shell where this is possible, either, save for Ruby where you have the string literal operators making escapes much easier.

I would suggest that before sending strings to external commands, that you convert the PowerShell escape sequences to the target runtime escape sequences. This isn't a problem unique to PowerShell, but is easier to work with in other shells because there is more of an overlap of the special characters between other runtimes.

codewario
  • 19,553
  • 20
  • 90
  • 159