What is the difference between "-gt 0" and "-eq $ true" when looking for non-empty string values?
I am collecting a list of all user accounts in AD that have a non-empty job title. First I get all users (I will filter later):
$allUsers = get-aduser -filter * -properties *
Then I only grab those accounts with non-empty headers. First I tried the following: "Well, if a value is present, it will evaluate to $ true."
$allUsers | ? {$_.Title -eq $true}
But this leads to empty lists. So, I tried the same as I did by doing the following:
$allUsers | ? {$_.Title -gt 0}
In this case, I get the expected result.
What is the difference between the two statements? My thought is that PowerShell -eq is like === in JavaScript. It is right?
source to share
This is because PowerShell is trying to coerce the right side of the comparison to be the left side.
$allUsers | ? {$_.Title -eq $true}
It doesn't work because it is the same as doing:
$allUsers | ? {$_.Title -eq "True"}
To find out why, try casting: [string]$true
On the other hand, if you did ( and I recommend you do ):
$allUsers | ? {$_.Title}
It would work as expected.
Likewise, when you do:
$allUsers | ? {$_.Title -gt 0}
This is how to do it:
$allUsers | ? {$_.Title -gt "0"}
This is theoretically a much more dangerous comparison, because a name starting with, say @
, will return false. In practice, it is unlikely that you will have a heading starting with the character value below 0
, since all upper and lower case letters have a higher value. But I am not considering internationalization.
Although for my own sake and for the sake of those who follow me, you would edit the post to explain exactly why {$ _. Title} is the preferred method?
I don't think this is the absolute best, but I like it for several reasons:
- In short.
- It contains no built-in constants. Not sure if it matters a lot, but it's less to be wrong.
- This (in my opinion) cleans up what you are testing as this is the usual way of testing this in many languages.
- It works with
$null
and with an empty string.
There are other ways:
$allUsers | ? { ![String]::IsNullOrEmpty($_.Title) } $allUsers | ? { $_.Title.Length -gt 0 } $allUsers | ? { $_.Title -ne "" } # would include $null titles $allUsers | ? { $_.Title -ne $null } # would include empty string titles
Something else I'm not addressing: you have to do this comparison inside a property -Filter
Get-ADUser
, and ideally you only need to query the properties you need:
$allUsers = Get-ADUser -Filter { -not (Title -like "*") } -Properties Title
The parameter -Filter
looks like a script block, but it has its own syntax and valid statements and values, so it's a little more complex. It should be much faster though.
source to share