¿Cómo buscar una cadena en varios archivos y devolver los nombres de los archivos en Powershell?

303

Empecé a aprender powershell hace un par de días, y no pude encontrar nada en Google que haga lo que necesito, así que por favor tengan en cuenta mi pregunta.

Me han pedido que reemplace algunas cadenas de texto en varios archivos. No necesariamente conozco la extensión de los posibles archivos de destino y tampoco sé su ubicación. Hasta ahora he logrado buscar recursivamente en el directorio ( get-ChildItem -recurse) y encontrar la cadena que estaba buscando con get-content y select-string:

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

El problema es que puedo ver las ocurrencias del texto que estoy buscando, pero no sé cómo decirle a PS que devuelva la ruta y el nombre de todos los archivos coincidentes.

¿Cómo puedo obtener el nombre y la ubicación de los archivos que contienen la expresión que estoy buscando?

Bluz
fuente
2
Quizás edite la pregunta para que sea más genérica. La respuesta a esta pregunta no tiene nada que ver con JBoss o su aplicación en la que está trabajando parece ...
Kolob Canyon
55
Acabo de ver tu comentario y edité mi pregunta ... ¡2 años después! mejor tarde que nunca .. :)
Bluz

Respuestas:

469

Esto debería dar la ubicación de los archivos que contienen su patrón:

Get-ChildItem -Recurse | Select-String "dummy" -List | Select Path
Jon Z
fuente
3
¿Qué pasa si también quieres MOVER esos archivos? ... Recibo un error con esto donde no puedo unirme a un | Move-Item hasta el final de eso.
rud3y
66
Move-Item no tiene nameparámetro. Intente agregar| %{Move-Item $_.name <destination>}
jon Z
49
Get-ChildItem -Recurse | Select-String "dummy" -List | Select Pathdevuelve solo la primera coincidencia para cada archivo, por lo que puede ser un poco más eficiente y evita la necesidad de agruparlos
ben
55
vale la pena notar que puede filtrar solo un cierto tipo de archivo, digamos txtarchivos, si lo usa Get-ChildItem -Recurse -Filter *.txten su lugar
Girardi
@ rud3y Le recomiendo que lo escriba en un script usando un foreachbucle si está haciendo operaciones grandes como esa. Se vuelve muy complicado cuando intentas hacer todo eso en una línea y es muy fácil cometer un gran error. Hablo por experiencia
Kolob Canyon
75

Aquí hay una variedad de respuestas precisas, pero aquí está el código más conciso para varias variaciones diferentes. Para cada variación, la línea superior muestra la sintaxis completa y la inferior muestra la sintaxis concisa.

El ítem (2) es una forma más concisa de las respuestas de Jon Z y manojlds, mientras que el ítem (1) es equivalente a las respuestas de vikas368 y buygrush.

  1. Listar objetos FileInfo para todos los archivos que contienen patrones:

    Get-ChildItem -Recurse filespec | Where-Object { Select-String pattern $_ -Quiet }
    ls -r filespec | ? { sls pattern $_ -q }
    
  2. Lista de nombres de archivos para todos los archivos que contienen patrones:

    Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
    ls -r filespec | sls pattern | select -u Path
    
  3. Listar objetos FileInfo para todos los archivos que no contienen patrón:

    Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }
    ls -r filespec | ? { !(sls pattern $_ -q) }
    
  4. Lista de nombres de archivos para todos los archivos que no contienen patrón:

    (Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }).FullName
    (ls -r filespec | ? { !(sls pattern $_ -q) }).FullName
    
Michael Sorens
fuente
Además, si solo está buscando Archivos que contengan el patrón en cualquier lugar, puede renunciar después de encontrar la primera instancia utilizando el -Listparámetro deSelect-String
KyleMit
Desearía que el OP hubiera hecho una ligera variación de la pregunta para que este fuera el AA. # 1 fue muy útil y es obvio que @Michael Sorens groks PS.
cBlaine
20

Esto mostrará la ruta, el nombre de archivo y la línea de contenido que encontró que coincide con el patrón.

Get-ChildItem -Path d:\applications\*config -recurse |  Select-String -Pattern "dummy" 
user5000502
fuente
Si sólo una línea se podría añadir entre los resultados :)
cladelpino
15

Canaliza el contenido de tu

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

a fl *

Verá que la ruta ya se devuelve como una propiedad de los objetos.

SI solo desea la ruta, use select patho select -unique pathpara eliminar duplicados:

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy" | select -unique path
manojlds
fuente
1
Gracias a los dos, esto es exactamente lo que estoy buscando. Desafortunadamente, cuando hay muchos subdirectorios involucrados en la ruta, PS corta la ruta absoluta y agrega tres puntos al final de la línea como \ dir1 \ dir2 \ dir3 \ ruta ... así que no sé qué archivo se devuelve . ¿Hay alguna manera de decirle a PS que sea menos codicioso con los personajes y se moleste en mostrar el camino completo? :) Muchas gracias !
Bluz
3
Debe agregar el -Fileinterruptor Get-ChildItemo terminará con una cascada interminable de errores al intentar llamar Get-Contenta los directorios.
RubberDuck
Si necesita la ruta completa, puede hacer esto. Las (Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy").FullNamepersonas parecen olvidar que PowerShell está orientado a objetos; en caso de duda, busque una propiedad
Kolob Canyon
10

Así es como lo haría, no necesita obtener contenido:

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

o

ls -r | Select-String dummy | fl *

Para ver cuáles son las diferentes propiedades ...

Esto es mas rapido. El segundo argumento es -filter:

ls -r . *.bat | select-string netsh
js2010
fuente
2
+1, esto funciona perfectamente para mi caso, sin embargo, utilícelo select Pattern, LineNumber, Filenamepara obtener resultados más concisos. La línea devuelve TODO en la línea que contiene su cadena de patrón. También puede enviarlo fácilmente a un csv si lo desea.
Protonova
9
Get-ChildItem -r | ? {$_.psiscontainer -eq $false} | ? {gc $_.pspath |select-string -pattern "dummy"}

Esto le dará los detalles completos de todos los archivos.

vikas368
fuente
Totalmente no sabía que -rfuncionaba. Supuse que siempre tenías que hacer-Recurse
Kolob Canyon
5

Para mantener los detalles completos del archivo en la matriz resultante, puede usar una ligera modificación de la respuesta publicada por vikas368 (que no parece funcionar bien con el autocompletado ISE):

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

o en resumen:

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

Si busca en un directorio, puede hacerlo:

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

Esto mostrará una lista de la ruta completa a cada archivo que contiene la cadena de búsqueda:

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

Tenga en cuenta que no muestra un encabezado sobre los resultados y no muestra las líneas de texto que contienen la cadena de búsqueda. Todo lo que le dice es dónde puede encontrar los archivos que contienen la cadena.

Niñita
fuente
2
¿Alguna idea de cómo mostrar el número de línea donde se encontró el patrón, junto con el nombre del archivo?
Piotr L
4

Modifiqué una de las respuestas anteriores para darme un poco más de información. Esto me ahorró una segunda consulta más adelante. Fue algo como esto:

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"

Puedo especificar la ruta y los comodines de archivo con estas estructuras, y guarda el nombre de archivo, el número de línea y la línea relevante en un archivo de salida.

RenoGreg
fuente
¡Frio! Gracias por esta solución adicional :) Sin embargo, ¿podría vincular a la respuesta en la que basó su solución y nombrar al autor de esa respuesta para dar crédito? ¡Gracias!
Max Vollmer