Come cercare una stringa in più file e restituire i nomi dei file in Powershell?


303

Ho iniziato a studiare PowerShell un paio di giorni fa e non sono riuscito a trovare nulla su Google che faccia ciò di cui ho bisogno, quindi ti preghiamo di tenere presente la mia domanda.

Mi è stato chiesto di sostituire alcune stringhe di testo in più file. Non conosco necessariamente l'estensione dei possibili file di destinazione e non conosco nemmeno la loro posizione. Finora sono riuscito a navigare ricorsivamente nella directory ( get-ChildItem -recurse) e trovare la stringa che stavo cercando con get-content e select-string:

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

Il problema è che posso vedere le occorrenze del testo che sto cercando, ma non so come dire a PS di restituire il percorso e il nome anche per ogni file corrispondente.

Come posso ottenere il nome e la posizione dei file che contiene l'espressione che sto cercando?


2
Forse modifica la domanda per essere più generico. La risposta a questa domanda non ha nulla a che fare con JBoss o la tua applicazione su cui stai lavorando sembra ...
Kolob Canyon

5
Ho appena notato il tuo commento e modificato la mia domanda ... 2 anni dopo! meglio tardi che mai .. :)
Bluz,

Risposte:


469

Questo dovrebbe indicare la posizione dei file che contengono il tuo modello:

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

3
Che cosa succede se si desidera spostare anche quei file? ... Sto ricevendo un errore con questo dove non riesco a unirmi a | Sposta-oggetto alla fine.
Rudy

6
Move-Item non ha nameparametri. Prova ad aggiungere| %{Move-Item $_.name <destination>}
jon Z

49
Get-ChildItem -Recurse | Select-String "dummy" -List | Select Pathrestituisce solo la prima corrispondenza per ogni file, quindi potrebbe essere un po 'più efficiente ed evita la necessità di raggrupparli
ben

5
vale la pena notare che è possibile filtrare solo per un determinato tipo di file, ad esempio txtfile, se si utilizza Get-ChildItem -Recurse -Filter *.txtinvece
Girardi

@ rud3y Ti consiglio vivamente di scriverlo in uno script usando un foreachciclo se stai facendo grandi operazioni del genere. Diventa molto contorto quando provi a fare tutto ciò su una riga ed è molto facile commettere un grosso errore. Parlo per esperienza
Kolob Canyon,

75

Ci sono una varietà di risposte accurate qui, ma qui è il codice più conciso per diverse varianti. Per ogni variazione, la riga superiore mostra la sintassi completa e quella inferiore mostra la sintassi concisa.

L'articolo (2) è una forma più concisa delle risposte di Jon Z e manijlds, mentre l'articolo (1) è equivalente alle risposte di vikas368 e buygrush.

  1. Elenca gli oggetti FileInfo per tutti i file contenenti pattern:

    Get-ChildItem -Recurse filespec | Where-Object { Select-String pattern $_ -Quiet }
    ls -r filespec | ? { sls pattern $_ -q }
    
  2. Elenca i nomi dei file per tutti i file contenenti pattern:

    Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
    ls -r filespec | sls pattern | select -u Path
    
  3. Elenca gli oggetti FileInfo per tutti i file che non contengono pattern:

    Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }
    ls -r filespec | ? { !(sls pattern $_ -q) }
    
  4. Elenca i nomi dei file per tutti i file che non contengono pattern:

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

Inoltre, se stai solo cercando File che contengono lo schema ovunque, puoi rinunciare dopo aver trovato la prima istanza utilizzando il -Listparametro diSelect-String
KyleMit

Vorrei che il PO avesse posto una leggera variazione della domanda in modo che questo fosse l'AA. # 1 è stato molto utile ed è ovvio che @Michael Sorens brontola PS!
cBlaine,

20

Verranno visualizzati il ​​percorso, il nome file e la riga di contenuto trovati corrispondenti al modello.

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

Se solo una linea potesse essere aggiunta tra i risultati :)
cladelpino

15

Pipa il contenuto del tuo

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

per fl *

Vedrai che il percorso è già stato restituito come proprietà degli oggetti.

Se vuoi solo il percorso, usa select patho select -unique pathper rimuovere i duplicati:

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

1
Grazie a entrambi, questo è esattamente quello che sto cercando. Sfortunatamente, quando ci sono molte sottodirectory coinvolte nel percorso, PS taglia il percorso assoluto e aggiunge tre punti alla fine della linea come \ dir1 \ dir2 \ dir3 \ path ... quindi non so quale file viene restituito . C'è un modo per dire a PS di essere meno avido di personaggi e preoccuparsi di mostrare l'intero percorso? :) Molte grazie !
Bluz,

3
È necessario aggiungere il -Filepassaggio a Get-ChildItemo si finisce con una cascata infinita di errori dal tentativo di chiamare le Get-Contentdirectory.
RubberDuck,

Se è necessario il percorso completo, è possibile farlo. Le (Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy").FullNamepersone sembrano dimenticare che PowerShell è orientato agli oggetti; in caso di dubbio, cercare una proprietà
Kolob Canyon

10

Ecco come lo farei, non è necessario ottenere contenuto:

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

o

ls -r | Select-String dummy | fl *

Per vedere quali sono le diverse proprietà ...

Questo è più veloce Il secondo argomento è -filter:

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

2
+1, Questo funziona perfettamente per il mio caso, tuttavia utilizzare select Pattern, LineNumber, Filenameper un output più conciso. La riga restituisce TUTTO sulla riga che contiene la stringa del modello. Puoi anche inviarlo facilmente a un csv se lo desideri.
Protonova,

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

Questo ti darà tutti i dettagli di tutti i file


Totalmente non sapevo che -rfunzionasse. Ho pensato che dovevi fare sempre-Recurse
Kolob Canyon,

5

Per mantenere i dettagli completi del file nell'array risultante, è possibile utilizzare una leggera modifica della risposta pubblicata da vikas368 (che non sembra funzionare bene con il completamento automatico ISE):

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

o in breve:

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

5

Se cerchi in una directory, puoi farlo:

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

4

Verrà visualizzato un elenco del percorso completo di ciascun file che contiene la stringa di ricerca:

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

Si noti che non visualizza un'intestazione sopra i risultati e non visualizza le righe di testo contenenti la stringa di ricerca. Tutto ciò che ti dice è dove puoi trovare i file che contengono la stringa.


2
Qualche idea su come visualizzare il numero di riga in cui è stato trovato il modello, insieme al nome del file?
Piotr L

4

Ho modificato una delle risposte sopra per darmi qualche informazione in più. Questo mi ha risparmiato una seconda domanda in seguito. Era qualcosa del genere:

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"

Posso specificare i caratteri jolly di percorso e file con queste strutture e salva il nome file, il numero di riga e la riga pertinente in un file di output.


Freddo! Grazie per questa soluzione aggiuntiva :) Tuttavia, potresti collegarti alla risposta su cui hai basato la tua soluzione e nominare l'autore di quella risposta per dare credito? Grazie!
Max Vollmer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.