Jak wyszukać ciąg w wielu plikach i zwrócić nazwy plików w programie Powershell?

303

Zacząłem uczyć się PowerShell kilka dni temu i nie mogłem znaleźć w Google niczego, co robi to, czego potrzebuję, więc proszę o odpowiedź na moje pytanie.

Poproszono mnie o zamianę niektórych ciągów tekstowych na wiele plików. Niekoniecznie znam rozszerzenie możliwych plików docelowych i nie znam ich lokalizacji. Do tej pory udało mi się rekursywnie przeglądać katalog ( get-ChildItem -recurse) i znaleźć szukany ciąg za pomocą get-content i select-string:

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

Problem polega na tym, że widzę wystąpienia tekstu, którego szukam, ale nie wiem, jak powiedzieć PS, aby zwrócił ścieżkę i nazwę dla każdego pasującego pliku.

Jak mogę uzyskać nazwę i lokalizację plików zawierających szukane wyrażenie?

Bluz
źródło
2
Może edytuj pytanie, aby było bardziej ogólne. Odpowiedź na to pytanie nie ma nic wspólnego z JBoss lub aplikacją, nad którą pracujesz, wydaje się ...
Kolob Canyon
5
Właśnie zauważyłem twój komentarz i zredagowałem moje pytanie ... 2 lata później! lepiej późno niż nigdy .. :)
Bluz

Odpowiedzi:

468

To powinno podać lokalizację plików, które zawierają twój wzorzec:

Get-ChildItem -Recurse | Select-String "dummy" -List | Select Path
jon Z
źródło
3
Co jeśli chcesz również PRZENOSIĆ te pliki? ... Występuje błąd z tym, że nie mogę dołączyć do | Przenieś przedmiot na koniec.
rud3y
6
Element Move nie ma nameparametru. Spróbuj dodać| %{Move-Item $_.name <destination>}
jon Z
49
Get-ChildItem -Recurse | Select-String "dummy" -List | Select Pathzwraca tylko pierwsze dopasowanie dla każdego pliku, więc może być nieco bardziej wydajne i pozwala uniknąć konieczności ich grupowania
ben
5
Warto zauważyć, że można filtrować tylko dla pewnego typu pliku, powiedzmy txtplików, jeśli używasz Get-ChildItem -Recurse -Filter *.txtzamiast
Girardi
@ rud3y Gorąco sugeruję, abyś napisał to w skrypcie za pomocą foreachpętli, jeśli wykonujesz takie duże operacje. Staje się bardzo skomplikowany, gdy próbujesz zrobić to wszystko w jednym wierszu i bardzo łatwo jest popełnić duży błąd. Mówię z doświadczenia
Kanion Kolob
74

Istnieje wiele dokładnych odpowiedzi tutaj, ale tutaj jest najbardziej zwięzły kod dla kilku różnych odmian. Dla każdej odmiany górny wiersz pokazuje pełną składnię, a dolny pokazuje zwięzłą składnię.

Pozycja (2) jest bardziej zwięzłą formą odpowiedzi Jona Z i manojldsa, podczas gdy pozycja (1) odpowiada odpowiedziom od vikas368 i buygrush.

  1. Wyświetl obiekty FileInfo dla wszystkich plików zawierających wzorzec:

    Get-ChildItem -Recurse filespec | Where-Object { Select-String pattern $_ -Quiet }
    ls -r filespec | ? { sls pattern $_ -q }
    
  2. Wyświetl nazwy plików dla wszystkich plików zawierających wzorzec:

    Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
    ls -r filespec | sls pattern | select -u Path
    
  3. Lista FileInfo obiektów dla wszystkich plików nie zawierających wzór:

    Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }
    ls -r filespec | ? { !(sls pattern $_ -q) }
    
  4. Lista nazw plików dla wszystkich plików nie zawierających wzór:

    (Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }).FullName
    (ls -r filespec | ? { !(sls pattern $_ -q) }).FullName
    
Michael Sorens
źródło
Ponadto, jeśli szukasz plików zawierających wzorzec w dowolnym miejscu, możesz zrezygnować po znalezieniu pierwszej instancji, używając -ListparametruSelect-String
KyleMit
Chciałbym, żeby OP zadał niewielką odmianę pytania, aby była to AA. # 1 był bardzo przydatny i oczywiste jest, że @Michael Sorens groks PS!
cBlaine,
20

Spowoduje to wyświetlenie ścieżki, nazwy pliku i znalezionej linii treści pasującej do wzorca.

Get-ChildItem -Path d:\applications\*config -recurse |  Select-String -Pattern "dummy" 
użytkownik5000502
źródło
Gdyby między wynikami można było dodać tylko linię :)
cladelpino,
15

Potokuj zawartość swojego

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

do fl *

Zobaczysz, że ścieżka jest już zwracana jako właściwość obiektów.

JEŚLI chcesz tylko ścieżki, użyj select pathlub, select -unique pathaby usunąć duplikaty:

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy" | select -unique path
manojlds
źródło
1
Dzięki wam obojgu właśnie tego szukam. Niestety, gdy w ścieżce występuje wiele podkatalogów, PS przecina ścieżkę bezwzględną i dodaje trzy kropki na końcu linii, takie jak \ dir1 \ dir2 \ dir3 \ path ... więc nie wiem, który plik jest zwracany . Czy istnieje sposób, aby powiedzieć PS, aby był mniej chciwy na postacie i zawracał sobie głowę pełną ścieżką? :) Wielkie dzięki !
Bluz,
3
Musisz dodać -Fileprzełącznik Get-ChildItemlub skończyć z niekończącą się kaskadą błędów podczas próby wywołania Get-Contentkatalogów.
RubberDuck
Jeśli potrzebujesz pełnej ścieżki, możesz to zrobić (Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy").FullName Ludzie zapominają, że PowerShell jest zorientowany obiektowo; w razie wątpliwości poszukaj nieruchomości
Kanion Kolob
10

Tak bym to zrobił, nie potrzebujesz treści:

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

lub

ls -r | Select-String dummy | fl *

Aby zobaczyć, jakie są różne właściwości ...

To jest szybsze. Drugi argument to -filter:

ls -r . *.bat | select-string netsh
js2010
źródło
2
+1, Działa to idealnie w moim przypadku, jednak użyj select Pattern, LineNumber, Filenamedla bardziej zwięzłego wydruku. Linia zwraca WSZYSTKO w wierszu zawierającym ciąg wzorca. Możesz również łatwo wyprowadzić to do pliku csv, jeśli chcesz.
Protonova,
9
Get-ChildItem -r | ? {$_.psiscontainer -eq $false} | ? {gc $_.pspath |select-string -pattern "dummy"}

To da ci pełne szczegóły wszystkich plików

vikas368
źródło
Zupełnie nie wiedziałem, że to -rdziała. Pomyślałem, że zawsze musisz to robić-Recurse
Kanion Kolob
5

Aby zachować pełne szczegóły pliku w wynikowej tablicy, możesz użyć niewielkiej modyfikacji odpowiedzi opublikowanej przez vikas368 (która nie działała dobrze z autouzupełnianiem ISE):

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

lub w skrócie:

ls -r | ?{ $_ | Select-String -Pattern "dummy" }
buygrush
źródło
5

Jeśli przeszukujesz jeden katalog, możesz to zrobić:

select-string -Path "c:\temp\*.*" -Pattern "result"  -List | select Path
Esperento57
źródło
4

Spowoduje to wyświetlenie listy pełnej ścieżki do każdego pliku zawierającego ciąg wyszukiwania:

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

Zauważ, że nie wyświetla nagłówka nad wynikami i nie wyświetla wierszy tekstu zawierających szukany ciąg. Wszystko, co mówi, to miejsce, w którym można znaleźć pliki zawierające ciąg.

Mała dziewczynka
źródło
2
Masz pomysł, jak wyświetlić numer wiersza, w którym znaleziono wzorzec, wraz z nazwą pliku?
Piotr L
4

Zmodyfikowałem jedną z powyższych odpowiedzi, aby uzyskać trochę więcej informacji. To oszczędzało mi później drugiego zapytania. To było coś takiego:

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"

Mogę określić ścieżkę i symbole wieloznaczne pliku za pomocą tych struktur i zapisuje nazwę pliku, numer linii i odpowiednią linię do pliku wyjściowego.

RenoGreg
źródło
Fajne! Dzięki za to dodatkowe rozwiązanie :) Czy mógłbyś jednak podać link do odpowiedzi, na której oparłeś swoje rozwiązanie i podać autora tej odpowiedzi, aby wyrazić uznanie? Dzięki!
Max Vollmer