I'm returning to powershell from bash after a long time, and I've found the where object behavior to be quite confusing.
Why does the following snippet return success? Nothing is found! Why does this not return failure like a grep would?
C:> Get-Process | ?{$_.name -like "laksdjfajsdfkjasdkf"}
C:> echo $?
True
tl;dr
# Run the command and, in addition to outputting to the console,
# collect the results in variable $result, via common parameter -OutVariable / -ov
# If you do NOT need to output to the console, simply use:
# $result = Get-Process | ...
Get-Process | ? { $_.name -like "laksdjfajsdfkjasdkf" } -ov result
# Test if the result is empty (using implicit Boolean conversion)
if (-not $result) { Write-Warning "Nothing matched." }
PowerShell's automatic (Boolean) $?
variable in PowerShell is not the (abstract) equivalent of exit codes in traditional shells, as PetSerAl points out.
$?
just tells you whether the last statement succeeded and the rules surrounding it are complicated, as the GitHub discussion that Owain Esau links to shows.
Succeeded means that no errors occurred, and a filtering operation not returning anything is success by that definition.
In short: $?
is of limited usefulness in PowerShell.
However, the exit code of the most recently executed external program is reflected in automatic variable $LASTEXITCODE
, so had you actually invoked grep
, its exit code would be reflected there.
(And while $?
is set immediately after execution of an external program to reflect $True
if the exit code was 0
and $False
otherwise, $?
may already reflect something else by the time the statement finishes, depending on the specifics of the statement, such as enclosing the call in (...)
)
In the case at hand you're looking to determine whether the filtering operation performed by the call to the Where-Object
cmdlet (invoked via its built-in alias ?
) returned any matches, but in PowerShell that status is not reflected anywhere separately.
Therefore, you must examine the output itself to determine whether anything matched, as shown in the snippet at the top.
There are no errors in this scenario, but for the sake of completeness: PowerShell's error handling is sophisticated, but complex, and again unlike that of traditional shells; you can find an overview here.