Confused about -or behavior in an If/Then construct

EDIT: Disregard this. My fault. :slight_smile:

$a = $null

if (!$a or (Test-Path 'C:\Windows')) {

}

Given this simple scenario, in what instances would Powershell evaluate the (Test-Path ‘C:\Windows’) condition? It seems to me it should begin evaluating from left to right. If this were the case, it would see that $a is null, check the -or operator and see that this means only 1 condition would need to evaluate true to make the entire if construct True and finish processing. However, I’m not seeing this to be the case.

Can anyone explain this?

The -or operator is a binary operation that “adds together” the value of the statements you’re testing, which means only one statement needs to be $true before it continues (1 + 0 is 1). The -and operator is a binary operation that “multiplies” the value of two statements, meaning both have to be $true for the evaluation to be $true (1 * 0 is 0).

Programming languages typically stop evaluating the rest of the if statement when it reaches a $true value, so as to not waste CPU cycles doing redundant checks, and the same goes for PowerShell.

An if statement is evaluated from left to right, so in your case you’re doing !$a first, then Test-Path.

You start by assigning $a a value of $null. Now an if statement needs a boolean value, that is a $true or $false value. If cast to a boolean type $null becomes $false, as does an empty string and the number 0, as demonstrated here:

PS C:\Users\mni> [bool]$null False PS C:\Users\mni> [bool]"" False PS C:\Users\mni> [bool]0 False

So what you’re doing is you’re saying if !$a is $true, then proceed. If !$a is $false, then try the next. With $a being null, !$a, or -not $a, is $true, and it never reaches Test-Path. If you want both/all the checks in your if statement to be $true in order to proceed, you want to use -and.

Now if you’re combining both -or and -and operators in your if statement, for example

if($x -eq 1 -and $y -eq 2 -or $z -eq 3) { }

PowerShell first evaluates if $x -eq 1 is $true, and if $y -eq 2 is $true. If this is the case, it proceeds. If it is not the case, it will then evaluate $z -eq 3, and if this is found to be $true it will proceed despite the value of $x and $y.