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
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.
(...).Name
uses member-access enumeration to extract all Name
property values from the file-info objects returned by Get-ChildItem
.
-match
, the regular-expression matching operator, due to operating on an array of values, returns the sub-array of matching values.
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.
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:
.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.