'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 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1