Вывести список имен файлов в папке, соответствующей шаблону, за исключением содержимого файла
Я использую ниже для рекурсивного перечисления всех файлов в папке, которая содержит $pattern
Get-ChildItem $targetDir -recurse | Select-String -pattern "$pattern" | group path | select name
Но, похоже, оба списка файлов имеют $pattern
в его названии и в его содержании, например, когда я запускаю выше, где $pattern="SAMPLE"
Я получил:
C:\tmp\config.include
C:\tmp\README.md
C:\tmp\specs\SAMPLE.data.nuspec
C:\tmp\specs\SAMPLE.Connection.nuspec
Сейчас:
C:\tmp\config.include
C:\tmp\README.md
на самом деле содержит SAMPLE ключевые слова / текст, но меня это не волнует, мне нужна только команда для вывода списка имен файлов, а не файлов с содержимым, соответствующим шаблону. Что мне не хватает?
Основываясь на ответах ниже, я также попробовал:
$targetDir="C:\tmp\"
Get-ChildItem $targetDir -recurse | where {$_.name -like "SAMPLE"} | group path | select name
а также:
$targetDir="C:\tmp\"
Get-ChildItem $targetDir -recurse | where {$_.name -like "SAMPLE"} | select name
но это не возвращает никаких результатов.
6 ответов
Select-String
делает то, что вы сказали. Акцент мой.
Командлет Select-String выполняет поиск текста и текстовых шаблонов во входных строках и файлах.
Так что, если вы просто ищете совпадение с именами файлов, просто используйте -Filter
из Get-ChildItem
или пост процесс с Where-Object
Get-ChildItem -Path $path -Recurse -Filter "*sample*"
Это должно вернуть все файлы и папки, которые имеют образец в своем имени. Если бы вы просто хотели файлы или каталоги, вы могли бы использовать переключатели -File
или же -Directory
вернуть эти конкретные типы объектов.
Если ваш шаблон более сложный, чем простое слово, вам может понадобиться Where-Object
как в ответе Ичидона с чем-то вроде -match
давая вам доступ к регулярным выражениям.
Логика группировки в вашем коде должна быть избыточной, поскольку вы возвращаете отдельные файлы с уникальными путями. Поэтому я не включил это здесь. Если вы просто хотите пути, вы можете Select-Object -Expand FullName
или просто (Get-ChildItem -Path $path -Recurse -Filter "*sample*").Fullname
get-ChildItem $targetDir -recurse | where {$_.name -like $pattern} | select name
В дополнение к полезному ответу Мэтта:
В частности, потому что к чему ты клонишь Select-String
являются [System.IO.FileInfo]
объекты - что есть что Get-ChildItem
выводит - вместо строк, это содержимое файлов, представленных этими объектами, ищется.
Предполагая, что вам нужно сопоставить только часть имени файла пути каждого файла и что ваш шаблон может быть выражен как выражение подстановки, вам не нужно Select-String
на всех и может вместо этого использовать Get-ChildItem
с -Filter
, как в ответе Мэтта, или медленнее, но немного мощнее -Include
,
Предостережение:
Select-String -Pattern
принимает регулярное выражение (например,.*sample.*
; увидетьGet-Help about_Regular_Expressions
),в то время как
Get-ChildItem -Filter/-Include
принимает подстановочное выражение (например,*sample*
; увидетьGet-Help about_Wildcards
) - это разные вещи.
Примечание: если ваше намерение состоит в том, чтобы сопоставлять только файлы, вы можете сказать Get-ChildItem
ограничить вывод файлами (в отличие от потенциально также каталогов), используя -File
(аналогично, вы можете ограничить вывод каталогами с помощью -Directory
).
Group-Object path
(group path
) не будет работать, как предполагалось, потому что .Path
свойство объектов информации о совпадении, выводимых Select-String
содержит полное имя файла, так что вы бы поместили каждый файл в отдельную группу - по сути, нет операции.
При использовании просто Get-ChildItem
, эквивалентное имя свойства будет .FullName
, но вам нужно сгруппировать по родительскому пути (путь к каталогу, в котором он находится), .DirectoryName
) Я полагаю, поэтому:
... | Group-Object DirectoryName | Select-Object Name
Это выводит полный путь каждого каталога, который содержит по крайней мере 1 файл с соответствующим именем файла.
(Обратите внимание, что Name
в Select-Object Name
относится к .Name
свойство групповых объектов, возвращаемых Group-Object
, который в этом случае является значением .DirectoryName
свойство на входных объектах.)
Чтобы дополнить отличный ответ @mklement0, вы можете попросить Powershell распечатать полный путь, добавив канал следующим образом:
Get-ChildItem -Recurse -ErrorAction SilentlyContinue -Force -Filter "*sample*" | %{$_.FullName}
Примечание: при поиске папок, в которых вы можете получить ошибку, связанную с безопасностью, мы используем параметр SilentlyContinue.
Я прошел ответ от @Itchydon
но не мог следовать за шаблоном '-like' $.
Я пытался перечислить файлы, содержащие 32 символа (буквы и цифры) в имени файла.
PS C:> Get-ChildItem C:\Users\ -Recurse | where {$_.name -match "[a-zA-Z0-9]{32}"} | select name
или
PS C:> Get-ChildItem C:\Users\010M\Documents\WindowsPowerShell -Recurse | Where-Object {$_.name -match "[A-Z0-9]{32}"} | select name
Итак, в этом случае не имеет значения, используете ли вы where или where-object.
Вы можете использовать строку выбора напрямую для поиска файлов, соответствующих определенной строке, да, это вернет имя файла:count:content ... и т. Д., Но внутри у них есть имена, которые вы можете выбрать или опустить, вам нужно "filename", чтобы сделать это, направить это в "select-object", выбрав "FileName" из вывода.
Итак, чтобы выбрать все файлы *.MSG с шаблоном "Тема: Веб-службы перезапущены", вы можете сделать следующее:
Select-String -Path. *.MSG -Pattern 'Subject: WebServices Restarted' -List | выберите объект имя файла
Кроме того, чтобы удалить эти файлы на лету, вы можете вставить оператор ForEach с помощью команды RM следующим образом:
Select-String -Path. *.MSG -Pattern 'Subject: WebServices Restarted' -List | выберите объект имя файла | foreach { rm $_.FileName }
Сам пробовал, работает на 100%.
надеюсь, это поможет