Implicit syntax in Powershell cmdlet Where-object

I am getting used to believing that these 2 commands are identical:

Get-childitem | Where-object { PSIsContainer }

Get-childitem | Where-object { $_.PSIsContainer }

However, I have a portion of code that reads:

$data = Import-csv $SomeExternalFile

$data = Select-object -Property Amount,Category |

Where-object { Category -NE 'Credits')

$SomeExternalFile is a very simple file with 2 columns (properties): Amount,Category. But I keep getting errors on the Where-object statement, PS saying that it doesn’t recognize “Category”.

But when I re-write the Where-object statement as:

Where-object { $_.Category -NE 'Credits' }

everything works perfectly and as expected.

Is there a genuine difference between:

Where-object { PropertyA      <comparison> <string> }

Where-object {$_.PropertyA <comparison> <string> }

Any help and/ore guidance would be highly appreciated.


You might be thinking of this way of writing it:

Get-childitem | Where-object PSIsContainer

Notice that it has no curlies. That is the short form. The limitation is that you can only do a single comparison.

When you use the curlies, the scriptblock, you need to tell powershell what object you are trying to access. $_ points to the current one.

Thanks very much, Mr phansen.

I also discovered that in writing:

Get-childitem | Get-member PSIsContainer

the " -EQ $True" portion is assumed by Powershell, i.e., it’s the same as

Get-childitem | Get-member PSIsContainer -eq $True

In reading the documentation, it is not clear what/which logical comparison operators can or cannot be omitted because they have “implicit defaults”. The test for $True seems obvious. Are there any others? Is there a source of reference that clearly states which one(s) have such features? Thanking you for your attention and kind consideration.

Get-childitem | Get-member PSIsContainer

Get-childitem | Get-member PSIsContainer -eq $True

Get-childitem | Where-object { PSIsContainer }

Get-childitem | Where-object { $_.PSIsContainer }

Get-childitem | Where-object PSIsContainer

#1 is wrong

#2 PSISContainer is positionally bound to -Name parameter of Get-Member cmdlet and fails for ‘-eq $True’ which is not valid.

#3 will also fail as PSISContainer is just an unrecognized until there is a cmdlet or function in that name.

#4 works as it resolves to the property PSISCOntainer of a FileInfo or DirectoryInfo object.

#5 works as there is a property PSISContainer and the which is having a value(finally convertible to True bool value). this Value is positionally bound to -Property parameter.

$CustomObject = [pscustomobject]@{r=1;t=0;rr=$true;tt=$false;other='something';novalue=''}

$CustomObject | Get-Member -Property r #Passes as r is having 1 and is similar to $true
$CustomObject | Get-Member -Property t #Evaluates to false as t is 0 which is similar to $false
$CustomObject | Get-Member -Property rr #Passes as r is $true
$CustomObject | Get-Member -Property tt #Evaluates to false as t is $false
$CustomObject | Get-Member -Property other #Passes as other is having some value and is similar to $true
$CustomObject | Get-Member -Property novalue #Evaluates to false as novalue is empty string which is similar to $false

Hmm, I get errors on these:

Get-childitem | Where-object { PSIsContainer }

PSIsContainer : The term 'PSIsContainer' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:32
+ Get-childitem | Where-object { PSIsContainer }
+                                ~~~~~~~~~~~~~

Get-childitem | Get-member PSIsContainer -eq $True

Get-Member : A parameter cannot be found that matches parameter name 'eq'.
At line:1 char:42
+ Get-childitem | Get-member PSIsContainer -eq $True
+                                          ~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Member], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetMemberCommand

But there is a short form of where-object that would work. (But you can’t do “get-childitem | where-object -not psiscontainer”.)

Get-childitem | Where-object PSIsContainer

Get-childitem | Where-object PSIsContainer -eq $True

See the examples that show both the long and short forms, and “comparision statement”: Where-Object (Microsoft.PowerShell.Core) - PowerShell | Microsoft Docs

My sincerest thanks Mr kvprasoon, your reply is very helpful.

Much appreciated.

To add: Unless you are running powershell 2, there is an even shorter way to list files and directories…

Get-ChildItem -Directory
Get-ChildItem -File