可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
Select-String
is doing what you told it to. Emphasis mine.
The Select-String cmdlet searches for text and text patterns in input strings and files.
So if you are just looking to match with file names just use -Filter
of Get-ChildItem
or post process with Where-Object
Get-ChildItem -Path $path -Recurse -Filter "*sample*"
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
回答2:
get-ChildItem $targetDir -recurse | where {$_.name -like $pattern} | select name
回答3:
To complement Matt's helpful answer:
Specifically, because what you're piping to Select-String
are [System.IO.FileInfo]
objects - which is what Get-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 use Get-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.*
; see Get-Help about_Regular_Expressions
),
whereas Get-ChildItem -Filter/-Include
accepts a wildcard expression (e.g., *sample*
; see Get-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 by Select-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:
... | Group-Object DirectoryName | Select-Object Name
This outputs the full path of each directory that contains at least 1 file with a matching file name.
(Note that the Name
in Select-Object Name
refers to the .Name
property of the group objects returned by Group-Object
, which in this case is the value of the .DirectoryName
property on the input objects.)
回答4:
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:
Select-String -Path .*.MSG -Pattern 'Subject: WebServices Restarted'
-List | select-object Filename
Also, to remove these files on the fly, you could pip into a ForEach statement with the RM command as follows:
Select-String -Path .*.MSG -Pattern 'Subject: WebServices Restarted'
-List | select-object Filename | foreach { rm $_.FileName }
I tried this myself, works 100%.
I hope this helps
回答5:
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.