I am using the below to recursively list all files in a folder that contains the $pattern
Get-ChildItem $targetDir -recurse | Select-String -pattern "$pattern" | group path | select name
But it seems it both list files having the $pattern
in its name and in its content, e.g. when I run the above where $pattern="SAMPLE"
I get:
C:\tmp\config.include
C:\tmp\README.md
C:\tmp\specs\SAMPLE.data.nuspec
C:\tmp\specs\SAMPLE.Connection.nuspec
Now:
C:\tmp\config.include
C:\tmp\README.md
indeed contains the SAMPLE keywords/text but I don't care about that, I only need the command to list file names not file with content matching the pattern. What am I missing?
Based on the below answers I have also tried:
$targetDir="C:\tmp\"
Get-ChildItem $targetDir -recurse | where {$_.name -like "SAMPLE"} | group path | select name
and:
$targetDir="C:\tmp\"
Get-ChildItem $targetDir -recurse | where {$_.name -like "SAMPLE"} | select name
but it does not return any results.
You can use select-string directly to search for files matching a certain string, yes, this will return the filename:count:content ... etc, but, internally these have names that you can chose or omit, the one you need is the "filename" to do this pipe this into "select-object" choosing the "FileName" from the output.
So, to select all *.MSG files that has the pattern of "Subject: Webservices restarted", you can do the following:
Also, to remove these files on the fly, you could pip into a ForEach statement with the RM command as follows:
I tried this myself, works 100%.
I hope this helps
I went through the answer by @Itchydon
but couldn't follow the use of '-like' $pattern.
I was trying to list files having 32characters(letters and numbers) in the filename.
PS C:>
Get-ChildItem C:\Users\ -Recurse | where {$_.name -match "[a-zA-Z0-9]{32}"} | select name
or
PS C:>
Get-ChildItem C:\Users\010M\Documents\WindowsPowerShell -Recurse | Where-Object {$_.name -match "[A-Z0-9]{32}"} | select name
So, in this case it doesn't matter whether you use where or where-object.
To complement Matt's helpful answer:
Specifically, because what you're piping to
Select-String
are[System.IO.FileInfo]
objects - which is whatGet-ChildItem
outputs - rather than strings, it is the contents of the files represented by these objects is being searched.Assuming that you need to match only the file name part of each file's path and that your pattern can be expressed as a wildcard expression, you do not need
Select-String
at all and can instead useGet-ChildItem
with-Filter
, as in Matt's answer, or the slower, but slightly more powerful-Include
.Caveat:
Select-String -Pattern
accepts a regular expression (e.g.,.*sample.*
; seeGet-Help about_Regular_Expressions
),whereas
Get-ChildItem -Filter/-Include
accepts a wildcard expression (e.g.,*sample*
; seeGet-Help about_Wildcards
) - they are different things.On a side note: If your intent is to match files only, you can tell
Get-ChildItem
to restrict output to files (as opposed to potentially also directories) using-File
(analogously, you can limit output to directories with-Directory
).Group-Object path
(group path
) will not work as intended, because the.Path
property of the match-information objects output bySelect-String
contains the full filename, so you'd be putting each file in its own group - essentially, a no-op.When using just
Get-ChildItem
, the equivalent property name would be.FullName
, but what you're looking for is to group by parent path (the containing directory's path),.DirectoryName
), I presume, therefore:This outputs the full path of each directory that contains at least 1 file with a matching file name.
(Note that the
Name
inSelect-Object Name
refers to the.Name
property of the group objects returned byGroup-Object
, which in this case is the value of the.DirectoryName
property on the input objects.)Select-String
is doing what you told it to. Emphasis mine.So if you are just looking to match with file names just use
-Filter
ofGet-ChildItem
or post process withWhere-Object
That should return all files and folders that have sample in their name. If you just wanted files or directories you would be able to use the switches
-File
or-Directory
to return those specific object types.If your pattern is more complicated than a simple word then you might need to use
Where-Object
like in Itchydon's answer with something like-match
giving you access to regex.The grouping logic in your code should be redundant since you are returning single files that all have unique paths. Therefore I have not included that here. If you just want the paths then you can pipe into
Select-Object -Expand FullName
or just(Get-ChildItem -Path $path -Recurse -Filter "*sample*").Fullname