I am trying to achieve a specific logic in PowerShell 1-liner that is similar to the following bash command:
{ $another_command_group ;} && { A ; { B && C ;} ;} && { $another_command_group ;}
{ A ; { B && C ;} ;}
The logic of this command is as follows:
PowerShell version: 7.26
OS: Windows
What I already tried:
( A ; ( B && C ) )
Not Working.
| Missing closing ')' in expression.
A ; ( B && C )
Worked though, but apparently this is not good enough, because I need the Parentheses ()
to make them a (group)
to stick with other (group)s
with AND &&
I am having trouble finding a one-liner Command to replicate this logic in PowerShell. I would greatly appreciate any suggestions or solutions.
A single pipeline chain, i.e. two or more possibly pipeline-connected commands connected via &&
or ||
, the pipeline-chain operators needs no enclosure - except situationally in (...)
, the grouping operator if clarifying precedence is necessary.
{ B && C ;}
in your Bash code can be represented as B && C
, or, if needed for precedence clarification, (B && C)
(note that, unlike in Bash, (...)
does not create a subshell in PowerShell).To execute multiple statements (a pipeline chain being one example of a statement) as a group, enclose them in a script block, { ... }
and also call that block with &
, the call operator or, if needed, for PowerShell code, with .
, the dot-sourcing operator.
That is, { ... }
alone does not result in execution - it just defines a reusable piece of PowerShell code that must be called on demand.
Also, unlike in Bash, the last statement inside { ... }
need not be ;
-terminated; ;
need only be placed between statements.
Unfortunately, unlike in Bash, a script-block call does not preserve the success status of the last command executed inside of it, which in turn means that script-block calls can not meaningfully participate in a pipeline chain, because they invariably signal success.
This applies analogously to script files (*.ps1
) as well, which, however, can signal success vs. failure via an explicit exit
statement, whose use is not an option in a script block (it would exit the script / session as a whole). While return
can be used to exit a script block, its purpose - unlike in Bash - is to output data, not to report an exit code.
Therefore, unfortunately, a hypothetical pipeline chain involving script-block calls (the analog of a group command in Bash (POSIX-compatible shells)) must be broken up into multiple statements involving tests of the automatic $LASTEXITCODE
variable, which does reflect the exit code of the most recent external-program / script-file call:
& { $another_command_group }
if ($LASTEXITCODE -eq 0) { & { A ; B && C } }
if ($LASTEXITCODE -eq 0) { & { $another_command_group } }
However, as you've discovered yourself - if practical - you can reformulate a script-block call to a logically equivalent single pipeline chain, whose success status does work as expected.
The example you provided is that & { A ; (B && C) }
(which itself is the loose analog of command group { A ; { B && C ;} ;}
from your Bash command) can be reformulated as a single pipeline chain as follows:
( ( A && B && C ) || ( B && C ) )
The above preserves the success status of whatever program executes last, and can therefore be used as-is in a larger pipeline chain.