Implicit syntax in Powershell cmdlet Where-object

Welcome Forums General PowerShell Q&A Implicit syntax in Powershell cmdlet Where-object

This topic contains 6 replies, has 4 voices, and was last updated by

 
Participant
1 month ago.

  • Author
    Posts
  • #128972

    Participant
    Points: 234
    Rank: Participant

    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        }
    
    Where-object {$_.PropertyA   }
    
    

    Any help and/ore guidance would be highly appreciated.

     

  • #128993

    Participant
    Points: 192
    Helping Hand
    Rank: Participant

    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.

    • #128999

      Participant
      Points: 234
      Rank: Participant

      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.

  • #129009

    Participant
    Points: 1,086
    Helping Hand
    Rank: Community Hero
    #1
    Get-childitem | Get-member PSIsContainer
    
    #2
    Get-childitem | Get-member PSIsContainer -eq $True
    
    #3
    Get-childitem | Where-object { PSIsContainer }
    
    #4
    Get-childitem | Where-object { $_.PSIsContainer }
    
    #5
    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
    
    $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
    
    • #129087

      Participant
      Points: 234
      Rank: Participant

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

      Much appreciated.

  • #129024
    js

    Participant
    Points: 413
    Helping Hand
    Rank: Contributor

    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": https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object?view=powershell-5.1

  • #129107

    Participant
    Points: 192
    Helping Hand
    Rank: Participant

    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

You must be logged in to reply to this topic.