'Is there a powershell pattern for if($?) { }
I find myself chaining these a lot, eg:
do-cmd-one
if($?)
{
do-cmd-two
}
...
then at the end:
if(!$?)
{
exit 1
}
I assume there's a pattern for this in powershell but I don't know it.
Solution 1:[1]
PowerShell (Core) 7.0 introduced Bash-like &&
and ||
operators called pipeline-chain operators.
They will not be back-ported to Windows PowerShell, however, as the latter will generally see no new features.
In short, instead of:
do-cmd-one; if ($?) { do-cmd-two }
Note: Up to PowerShell 7.1, the more robust formulation is actuallydo-cmd-one; if ($LASTEXITCODE -eq 0) { do-cmd-two }
, for the reasons explained in this answer.
you can now write:
do-cmd-one && do-cmd-two
&&
(AND) and ||
(OR) implicitly operate on each command's implied success status, as reflected in automatic Boolean variable $?
.
This will likely be more useful with external programs, whose exit codes unambiguously imply whether $?
is $true
(exit code 0
) or $false
(any nonzero exit code).
By contrast, for PowerShell commands (cmdlets) $?
just reflects whether the command failed as a whole (a statement-terminating error occurred) or whether at least one non-terminating error was reported; the latter doesn't necessarily indicate overall failure.
However, there are plans to allow PowerShell commands to set $?
directly, as a deliberate overall-success indicator.
Also note that the following do not work with &&
and ||
:
PowerShell's
Test-*
cmdlets, because they signal the test result by outputting a Boolean rather than by setting$?
; e.g.,Test-Path $somePath || Write-Warning "File missing"
wouldn't work.Boolean expressions, for the same reason; e.g.,
$files.Count -gt 0 || write-warning 'No files found'
wouldn't work.
See this answer for background information, and the discussion in GitHub issue #10917.
There's a syntax caveat: As of this writing, the following will not work:
do-cmd-one || exit 1 # !! Currently does NOT work
Instead, you're forced to wrap exit
/ return
/ throw
statements in $(...)
, the so-called subexpression operator:
do-cmd-one || $(exit 1) # Note the need for $(...)
GitHub issue #10967 discusses the reasons for this awkward requirement, which are rooted in the fundamentals of PowerShell's grammar.
Solution 2:[2]
Not sure if you like this any better.
if($(do-cmd-one; $?))
{
do-cmd-two
}
else
{
exit 1
}
Some other ideas. If actually doesn't check the exit code of a command. But if a command has no output when failing, and has output when successful, it can work. In this case, I'm hiding the error messages. If will always hide a command's regular output.
if(test-connection -Count 1 microsoft.com 2>$null) { 'yes' } # never responds
if(test-connection -Count 1 yahoo.com 2>$null) { 'yes' }
yes
Test-connection happens to have a quiet option that returns a boolean anyway:
if(test-connection -count 1 yahoo.com -quiet) { 'yes' }
yes
if(test-connection -count 1 microsoft.com -quiet) { 'yes' }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |