Update: && and || have finally come to PowerShell (Core), namely in v7, termed pipeline-chain operators; see this answer for details.
Many years after the question was first asked, let me summarize the behavior of Windows PowerShell, whose latest and final version is 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, e.g.:# Equivalent of && command1 -arg1 -arg2; if ($?) { command2 -arg1 } # Equivalent of || command1 -arg1 -arg2; if (-not $?) { command2 -arg1 } -
Better alternative for external programs, using the automatic
$LASTEXITCODEvariable; this is preferable, because$?in Windows PowerShell can yield false negatives (no longer in PowerShell (Core) 7.2+), if a2>redirection is involved – see this answer:# Equivalent of && command1 -arg1 -arg2; if ($LASTEXITCODE -eq 0) { command2 -arg1 } # Equivalent of || command1 -arg1 -arg2; if ($LASTEXITCODE -ne 0) { command2 -arg1 } -
See below for why PowerShell’s
-andand-orare generally not a solution.
-
-
[Since implemented in PowerShell (Core) 7+] 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 && 1yields 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$truein a Boolean context, so if there’s at least one entry, the expression evaluates to$true.- However, the error information resulting from nonexistent file
nosuchfileis passed through, because errors are sent to a separate stream.
- However, the error information resulting from nonexistent file
-
Given that
Get-ChildItem \, nosuchfilereturns non-empty success output, the LHS evaluated to$true, so-andalso 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
-andexpression is$true, which is (the only success) output.
The net effect is:
-
The success output from both sides of the
-andexpression is consumed during evaluation and therefore effectively hidden. -
The expression’s only (success) output is its Boolean result, which is
$truein this case (which renders asTruein the terminal).