Search code examples
powershellfindstrselect-string

Remove the at symbol ( @ ) and curly bracket ( { ) from Select-Sring output in Powershell


I'm parsing filenames in Powershell, and when I use Get-ChildItem | select name, I get a clean output of the files:

file1.txt file2.txt file3.txt

But when I try to narrow down those files with Select-String, I'm getting a weird @ and { in front of my output:

Get-ChildItem | select name | Select-String -Pattern "1"

@{file1.txt}

Is there a parameter I'm missing? If I pipe with findstr rather than Select-String it works like a charm:

Get-ChildItem | select name | Findstr "1"

file1.txt


Solution

  • You can simplify and speed up your command as follows:

    @((Get-ChildItem).Name) -match '1'
    

    Note: @(), the array-subexpression operator, is needed to ensure that -match operates on an array, even if only one file happens to exist in the current dir.


    To make your original command work:

    Get-ChildItem | select -ExpandProperty Name | 
      Select-String -Pattern "1" | select -ExpandProperty Line
    
    • select -ExpandProperty Name makes select (Select-Object) return only the Name property values; by default (implied -Property parameter), a custom object that has a Name property is returned.

    • select -ExpandProperty line similarly extracts the Line property value from the Microsoft.PowerShell.Commands.MatchInfo instances that Select-String outputs.

      • Note that in PowerShell [Core] v7+ you could omit this step by instead using Select-String's (new) -Raw switch to request string-only output.

    As for what you tried:

    As stated, by not using -ExpandProperty, select name (implied -Property parameter) created a custom object ([pscustomobject] instance) with a Name property.

    Select-String stringifies its input objects, if necessary, so it can perform a string search on them, which results in the representation you saw; here's a simulation:

    # Stringify a custom object via an expandable string ("...")
    PS> "$([pscustomobject] @{ Name = 'file1.txt' })"
    @{Name=file1.txt}
    

    As an aside:

    • The above stringification method is essentially like calling .ToString() on the input objects[1], which often results in useless string representations (by default, just the type name); a more useful and intuitive stringification would be to use PowerShell's rich output-formatting system, i.e. to use the string representation you would see in the console; changing Select-String's behavior to do that is the subject of this feature request on GitHub.

    [1] Calling .ToString() directly on a [pscustomobject] instance is actually still broken as of PowerShell Core 7.0.0-rc.2, due to this bug; the workaround is to call .psobject.ToString() or to use an expandable string, as shown above.