Як шукати рядок у кількох файлах та повертати назви файлів у Powershell?


303

Я почав вивчати власні парення пару днів тому, і я не міг знайти нічого в Google, що робить те, що мені потрібно, тож будь ласка, поставтеся до мого запитання.

Мене попросили замінити деякі текстові рядки на кілька файлів. Я не обов'язково знаю розширення можливих цільових файлів, а також не знаю їх розташування. Поки мені вдалося рекурсивно перейти в каталог ( get-ChildItem -recurse) і знайти рядок, який я шукав, за допомогою get-content та select-string:

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy"

Проблема полягає в тому, що я бачу виникнення тексту, який я шукаю, але я не знаю, як сказати PS, щоб повернути шлях і ім'я для всіх відповідних файлів.

Як я можу отримати ім’я та розташування файлів, що містять вираження, яке я шукаю?


2
Можливо, відредагуйте питання, щоб бути більш загальним. Відповідь на це запитання не має нічого спільного з JBoss або вашим додатком, над яким ви працюєте, здається ...
Колоб Каньйон

5
Я щойно помітив ваш коментар і відредагував моє запитання ... через 2 роки! краще пізно ніж ніколи :) :)
Блюз

Відповіді:


468

Це має вказати розташування файлів, що містять ваш шаблон:

Get-ChildItem -Recurse | Select-String "dummy" -List | Select Path

3
Що робити, якщо ви також хочете перемістити ці файли? ... Я отримую помилку з цим, коли я не можу приєднатися до | Переміщення-предмет до кінця.
rud3y

6
Параметр "Переміщення" не має nameпараметра. Спробуйте додати| %{Move-Item $_.name <destination>}
jon Z

49
Get-ChildItem -Recurse | Select-String "dummy" -List | Select Pathповертає лише першу відповідність для кожного файлу, тому може бути трохи ефективнішою і уникає необхідності групувати їх
ben

5
варто зауважити, що ви можете фільтрувати лише певний тип файлу, скажімо, txtфайли, якщо ви використовуєте Get-ChildItem -Recurse -Filter *.txtзамість цього
Girardi

@ rud3y Я настійно пропоную вам написати це в сценарії, використовуючи foreachцикл, якщо ви робите такі великі операції. Це стає дуже заплутаним, коли ви намагаєтеся робити все це за один рядок, і дуже легко зробити велику помилку. Я кажу з досвіду
Колобський каньйон

74

Тут є безліч точних відповідей, але ось найкоротший код для кількох різних варіацій. Для кожного варіанту верхній рядок показує повний синтаксис, а нижній - короткий синтаксис.

Пункт (2) є більш стислою формою відповідей Джона Z та manojlds, тоді як пункт (1) еквівалентний відповідям від vikas368 та buygrush.

  1. Список об'єктів FileInfo для всіх файлів, що містять шаблон:

    Get-ChildItem -Recurse filespec | Where-Object { Select-String pattern $_ -Quiet }
    ls -r filespec | ? { sls pattern $_ -q }
    
  2. Список імен файлів для всіх файлів, що містять шаблон:

    Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
    ls -r filespec | sls pattern | select -u Path
    
  3. Перерахуйте об'єкти FileInfo для всіх файлів, що не мають шаблону:

    Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }
    ls -r filespec | ? { !(sls pattern $_ -q) }
    
  4. Список імен файлів для всіх файлів, що не мають шаблону:

    (Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }).FullName
    (ls -r filespec | ? { !(sls pattern $_ -q) }).FullName
    

Крім того, якщо ви просто шукаєте файли, які містять шаблон, де завгодно, ви можете відмовитись, знайшовши перший екземпляр, скориставшись -ListпараметромSelect-String
KyleMit

Я хотів би, щоб ОП поставила невелику варіацію питання, щоб це було АА. №1 було дуже корисно, і очевидно, що @Michael Sorens groks PS!
cBlaine

20

Це покаже шлях, ім'я файлу та рядок вмісту, який він знайшов, що відповідає шаблону.

Get-ChildItem -Path d:\applications\*config -recurse |  Select-String -Pattern "dummy" 

Якби між результатами міг бути доданий лише рядок :)
cladelpino

15

Трубопровідний вміст

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy"

до fl *

Ви побачите, що шлях вже повертається як властивість об'єктів.

Якщо ви хочете лише шлях, використовуйте select pathабо select -unique pathвидаляйте дублікати:

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy" | select -unique path

1
Завдяки вам обом, саме це я шукаю. На жаль, коли в шляху задіяно багато підкаталогів, PS вирізає абсолютний шлях і додає три крапки в кінці рядка, як \ dir1 \ dir2 \ dir3 \ path ... тому я не знаю, який файл повертається . Чи є спосіб сказати PS бути менш жадібними до персонажів і не турбуватися про показ повного шляху? :) Дуже дякую !
Блуз

3
Вам потрібно додати -Fileкомутатор до Get-ChildItemабо закінчується нескінченним каскадом помилок від спроби зателефонувати Get-Contentв каталоги.
RubberDuck

Якщо вам потрібен повний шлях, ви можете це зробити. (Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy").FullNameЛюди, здається, забувають, що PowerShell орієнтована на об'єкти; коли ви сумніваєтесь, шукайте нерухомість
Калонь Колоб

10

Ось як я це зробив, вам не потрібен get-content:

ls -r | Select-String dummy | select line,path

або

ls -r | Select-String dummy | fl *

Щоб побачити, які різні властивості ...

Це швидше. Другий аргумент - -фільтр:

ls -r . *.bat | select-string netsh

2
+1, Це чудово працює в моєму випадку, проте використовувати select Pattern, LineNumber, Filenameдля більш короткого виводу. Рядок повертає ВСЕ, що містить рядок шаблону. Ви також можете легко вивести це в csv, якщо хочете.
Protonova

9
Get-ChildItem -r | ? {$_.psiscontainer -eq $false} | ? {gc $_.pspath |select-string -pattern "dummy"}

Це дасть вам повну інформацію про всі файли


Повністю не знав, що -rпрацює. -Recurse
Зрозуміло, що

5

Щоб зберегти повну інформацію про файл у отриманому масиві, ви можете використати незначну модифікацію відповіді, опублікованої vikas368 (яка, здається, не добре працює з автоматичним заповненням ISE):

Get-ChildItem -Recurse | Where-Object { $_ | Select-String -Pattern "dummy" }

або коротше:

ls -r | ?{ $_ | Select-String -Pattern "dummy" }

5

Якщо ви шукаєте в одному каталозі, ви можете це зробити:

select-string -Path "c:\temp\*.*" -Pattern "result"  -List | select Path

4

Тут з’явиться список повного шляху до кожного файлу, що містить рядок пошуку:

foreach ($file in Get-ChildItem | Select-String -pattern "dummy" | Select-Object -Unique path) {$file.path}

Зауважте, що він не відображає заголовок над результатами та не відображає рядки тексту, що містять пошуковий рядок. Все, що вам каже, це те, де ви можете знайти файли, що містять рядок.


2
Будь-яка ідея, як відобразити номер рядка, де знайдено візерунок, разом із назвою файлу?
Пьотр Л

4

Я змінив одну з відповідей вище, щоб дати мені трохи більше інформації. Це пізніше позбавило мене другого запиту. Це було щось подібне:

Get-ChildItem `
        -Path "C:\data\path" -Filter "Example*.dat" -recurse | `
    Select-String -pattern "dummy" | `
    Select-Object -Property Path,LineNumber,Line | `
    Export-CSV "C:\ResultFile.csv"

Я можу вказати шлях і файлові символи за допомогою цієї структури, і це зберігає ім'я файлу, номер рядка та відповідний рядок у вихідний файл.


Класно! Дякую за це додаткове рішення :) Однак ви можете, будь ласка, посилатись на відповідь, на якому ви базували своє рішення, та ім'я автора цієї відповіді, щоб дати кредит? Дякую!
Макс Волмер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.