In Bash I can easily do something like
command1 && command2 || command3
which means to run command1 and if command1 succeeds to run command2 and if command1 fails to run command3.
What's the equivalent in PowerShell?
What Bash must be doing is implicitly casting the exit code of the commands to a Boolean when passed to the logical operators. PowerShell doesn't do this - but a function can be made to wrap the command and create the same behavior:
> function Get-ExitBoolean($cmd) { & $cmd | Out-Null; $? }
($? is a bool containing the success of the last exit code)
Given two batch files:
#pass.cmd
exit
and
#fail.cmd
exit /b 200
...the behavior can be tested:
> if (Get-ExitBoolean .\pass.cmd) { write pass } else { write fail }
pass
> if (Get-ExitBoolean .\fail.cmd) { write pass } else { write fail }
fail
The logical operators should be evaluated the same way as in Bash. First, set an alias:
> Set-Alias geb Get-ExitBoolean
Test:
> (geb .\pass.cmd) -and (geb .\fail.cmd)
False
> (geb .\fail.cmd) -and (geb .\pass.cmd)
False
> (geb .\pass.cmd) -and (geb .\pass.cmd)
True
> (geb .\pass.cmd) -or (geb .\fail.cmd)
True
Many years after the question was first asked, let me summarize the state of affairs as of PowerShell v5.1:
Bash's /
cmd
's&&
and||
control operators have NO PowerShell equivalents, and since you cannot define custom operators in PowerShell, there are no good workarounds:Use separate commands (on separate lines or separated with
;
), and explicitly test the success status of each command via automatic variable$?
, such as:command1 -arg1 -arg2; if ($?) { command2 -arg1 } # equivalent of &&
command1 -arg1 -arg2; if (-not $?) { command2 -arg1 } # equivalent of ||
See below for why PowerShell's
-and
and-or
are generally not a solution.
There was talk about adding them a while back, but it seemingly never made the top of the list.
- Now that PowerShell has gone open-source, an issue has been opened on GitHub.
- The tokens
&&
and||
are currently reserved for future use in PowerShell, so there's hope that the same syntax as in Bash can be implemented.
(As of PSv5.1, attempting something like1 && 1
yields error messageThe token '&&' is not a valid statement separator in this version.
)
Why PowerShell's -and
and -or
are no substitute for &&
and ||
:
Bash's control operators &&
(short-circuiting logical AND) and ||
(short-circuiting logical OR) implicitly check the success status of commands by their exit codes, without interfering with their output streams; e.g.:
ls / nosuchfile && echo 'ok'
Whatever ls
outputs -- both stdout output (the files in /
) and stderr output (the error message from attempting to access non-existent file nosuchfile
) -- is passed through, but &&
checks the (invisible) exit code of the ls
command to decide if the echo
command - the RHS of the &&
control operator - should be executed.
ls
reports exit code 1
in this case, signaling failure -- because file nosuchfile
doesn't exist -- so &&
decides that ls
failed and, by applying short-circuiting, decides that the echo
command need not be executed.
Note that it is exit code 0
that signals success in the world of cmd.exe
and bash
, whereas any nonzero exit code indicates failure.
In other words: Bash's &&
and ||
operate completely independently of the commands' output and only act on the success status of the commands.
PowerShell's -and
and -or
, by contrast, act only on the commands' standard (success) output, consume it and then output only the Boolean result of the operation; e.g.:
(Get-ChildItem \, nosuchfile) -and 'ok'
The above:
uses and consumes the success (standard) output -- the listing of
\
-- and interprets it as a Boolean; a non-empty input collection is considered$true
in a Boolean context, so if there's at least one entry, the expression evaluates to$true
.- However, the error information resulting from nonexistent file
nosuchfile
is passed through, because errors are sent to a separate stream.
- However, the error information resulting from nonexistent file
Given that
Get-ChildItem \, nosuchfile
returns non-empty success output, the LHS evaluated to$true
, so-and
also evaluates the RHS,'ok'
, but, again, consumes its output and interprets it as a Boolean, which, as a nonempty string, also evaluates to$true
.Thus, the overall result of the
-and
expression is$true
, which is (the only success) output.
The net effect is:
The success output from both sides of the
-and
expression is consumed during evaluation and therefore effectively hidden.The expression's only (success) output is its Boolean result, which is
$true
in this case (which renders asTrue
in the terminal in English-language systems).
We can use try catch finally method instead of using && method in powershell.
try {hostname} catch {echo err} finally {ipconfig /all | findstr bios}
来源:https://stackoverflow.com/questions/2416662/what-are-the-powershell-equivalents-of-bashs-and-operators