Вывести список имен файлов в папке, соответствующей шаблону, за исключением содержимого файла

Я использую ниже для рекурсивного перечисления всех файлов в папке, которая содержит $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%.

надеюсь, это поможет

Другие вопросы по тегам