Confused about -or behavior in an If/Then construct

This topic contains 1 reply, has 2 voices, and was last updated by Profile photo of Martin Nielsen Martin Nielsen 2 years, 10 months ago.

  • Author
    Posts
  • #15981
    Profile photo of Adam Bertram
    Adam Bertram
    Moderator

    EDIT: Disregard this. My fault. 🙂

    $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?

  • #16003
    Profile photo of Martin Nielsen
    Martin Nielsen
    Participant

    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.

You must be logged in to reply to this topic.