Truth in PowerShell

PowerShell does a lot of hand holding for you, which generally makes using it really easy.  For example, the concept of "true" is very important when building logical structures in a script, and PowerShell does its best to help you out.  And it generally does a good job, but there are some details that you should probably be aware of.  The below are all true statements:
  • "true" -eq $TRUE
  • "false" -eq $FALSE
  • "false" -ne $TRUE
  • if("true"){$TRUE}
  • if("false"){$TRUE}
So, what's happening with that last one, if we know that "false" does not -eq $TRUE?  Well, -eq is your buddy, and when you ask it if a string that reads "true" is equal to the boolean $TRUE condition, it says, "sure!".  Same thing, when you ask it if a string that reads "false" is a boolean $FALSE, it knows what you're asking and will tell you that it is indeed $FALSE.  It reads your string and figures that, if you're asking it about the word true, you probably mean the boolean value of $TRUE rather than just another string.

If, on the other hand, as well as its partners like Where-Object, doesn't let -eq chime in.  When you pass a string to if or to ?, they are simply checking to see if that string exists (is not $NULL or empty), meaning that they aren't going to parse that string at all to see if maybe perhaps you sortof meant $TRUE or $FALSE, the way -eq does.

So, long and short, remember this:
Although "false" equals $FALSE, if("false") is $TRUE.

Update:
Jeff saw my blog post and explored the situation himself.  He realized an important detail that led to a better understanding of what's actually happening here:

  • "false" -eq $FALSE
  • $FALSE -ne "false"
Since PowerShell is a loosely typed language, he figures that there's some implicit casting going on with these operations.  The operator on the right is being cast as whatever datatype the operator on the left is, which explains the results that we've seen (and if and where-object are looking for boolean data).

$FALSE is a boolean and "false" is a string (which you can verify by looking at $false.GetType().name and "false".GetType().name).  If you cast $FALSE as a string, by doing [string]$false, it will return the string "false".  I feel like I'm belaboring the point when I observe that "false" does, in fact, equal "false", but it's important.

So, what happens when we cast "false" as a boolean (which is what's happening in that second example that he pointed out)?  [boolean]"false" returns TRUE, because the string contains content.  [boolean]"any text you feel like putting in here" will always return TRUE, because there is content in the string.  So, that second line is resolving to $FALSE -ne $TRUE.  This casting behavior neatly explains what PowerShell is doing with -eq that makes it easy to use (but, also easy to misuse).

Comments

  1. Fascinating nuance that can lead to some very non-intuitive script behavior! Great post!

    ReplyDelete

Post a Comment

Sorry guys, I've been getting a lot of spam recently, so I've had to turn on comment moderation. I'll do my best to moderate them swiftly after they're submitted,

Popular posts from this blog

Clone a Standard vSwitch from one ESXi Host to Another

PowerShell Sorting by Multiple Columns

Deleting Orphaned (AKA Zombie) VMDK Files