Recorrer archivos en un directorio usando PowerShell

243

¿Cómo puedo cambiar el siguiente código para ver todos los archivos .log en el directorio y no solo un archivo?

Necesito recorrer todos los archivos y eliminar todas las líneas que no contienen "step4" o "step9". Actualmente, esto creará un nuevo archivo, pero no estoy seguro de cómo usar el for eachbucle aquí (novato).

Los archivos reales se nombran así: 2013 09 03 00_01_29.log . Me gustaría que los archivos de salida los sobrescriban, o que tengan el MISMO nombre, junto con "out".

$In = "C:\Users\gerhardl\Documents\My Received Files\Test_In.log"
$Out = "C:\Users\gerhardl\Documents\My Received Files\Test_Out.log"
$Files = "C:\Users\gerhardl\Documents\My Received Files\"

Get-Content $In | Where-Object {$_ -match 'step4' -or $_ -match 'step9'} | `
Set-Content $Out
usuario2725402
fuente

Respuestas:

363

Prueba esto:

Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files" -Filter *.log | 
Foreach-Object {
    $content = Get-Content $_.FullName

    #filter and save content to the original file
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content $_.FullName

    #filter and save content to a new file 
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content ($_.BaseName + '_out.log')
}
Shay Levy
fuente
Gracias. La parte BaseName no funciona (versión 1), pero logré crear primero una copia de seguridad del archivo completo y luego hacer el cambio al archivo original.
user2725402
66
Para v1, puede usar lo siguiente para extraer el nombre base: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy
Si reemplazo BaseNamecon FullName, obtengo lo que quiero.
M--
78

Para obtener el contenido de un directorio puede usar

$files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\"

Entonces puedes recorrer esta variable también:

for ($i=0; $i -lt $files.Count; $i++) {
    $outfile = $files[$i].FullName + "out" 
    Get-Content $files[$i].FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Una forma aún más fácil de poner esto es el foreachbucle (gracias a @Soapy y @MarkSchultheiss):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}
PVitt
fuente
Esto crea un archivo de salida llamado "out.log". ¿Cómo puedo crear un archivo de salida separado para cada archivo de entrada?
user2725402
@ user2725402 Agregué un archivo de salida dependiente de entrada que se llama <input file name> out
PVitt
no estoy seguro de lo que estoy haciendo mal, pero esto no funciona: ahora no obtengo archivos de salida (ni errores): $files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\" $files | Where-Object { $outFile = $_.Name + "out" Get-Content $_.FullName | Where-Object { $_ -match 'step4' -or $_ -match 'step9' } | Set-Content $outFile }
user2725402
2
También puedes hacerloforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy
1
o usarForEach ($f in $files){...}
Mark Schultheiss
31

Si necesita recorrer dentro de un directorio de forma recursiva para un tipo particular de archivo, use el siguiente comando, que filtra todos los archivos de doctipo de archivo

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc

Si necesita hacer la filtración en varios tipos, use el siguiente comando.

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc,*.pdf

Ahora las $fileNamesvariables actúan como una matriz desde la que puede recorrer y aplicar su lógica empresarial.

Sarath Avanavu
fuente
Lo que me molestó fue la omisión de archivos ocultos y / o del sistema. Para verlos también, debe usar el -Forceparámetro Get-ChildItem. Vea su documento en docs.microsoft.com/en-us/powershell/module/… .
til_b
-6

Otras respuestas son geniales, solo quiero agregar ... un enfoque diferente que se puede usar en PowerShell: instale utilidades GNUWin32 y use grep para ver las líneas / redirigir la salida al archivo http://gnuwin32.sourceforge.net/

Esto sobrescribe el nuevo archivo cada vez:

grep "step[49]" logIn.log > logOut.log 

Esto agrega la salida del registro, en caso de que sobrescriba el archivo logIn y desee conservar los datos:

grep "step[49]" logIn.log >> logOut.log 

Nota: para poder utilizar utilidades GNUWin32 a nivel mundial, debe agregar la carpeta bin a la ruta del sistema.

usuario1628658
fuente
18
Esta pregunta fue etiquetada como PowerShell, no Unix
SteveC
2
Si. Obviamente. Mi opinión fue bastante simple: puede usar las utilidades GNUWin32 en Windows, por lo tanto, puede usar fácilmente las herramientas * nix en Powershell. Trabajos. Nadie dijo nunca que la respuesta tenía que ser completamente nativa de Powershell. E incluso si lo hicieran, aún puede llamar a Win32 Utils directamente desde Powershell. AFAIK usando lo que esté disponible y sea compatible no es realmente algo malo.
user1628658
2
Hubiera editado mi comentario anterior, pero pasé el límite de 5 minutos: SteveC: ¿Estás diciendo que incorporar herramientas GNU que funcionan bien en Windows de alguna manera desafía a Powershell? Eso es una cosa. Entiendo que resolver esto solo en Powershell podría ser más productivo a corto plazo. A largo plazo, ampliar las posibilidades tiene más mérito. Agrega más opciones y está trabajando completamente en Windows y Powershell sin ningún emulador de Linux como Cygwin. Entonces, aunque entiendo su reserva, no estoy de acuerdo.
user1628658
55
La pregunta era sobre buscar en PowerShell, no sobre la multitud de otros idiomas que podrían usarse.
SteveC
1
Las respuestas están destinadas a ser la pregunta. Esta pregunta era explícita porque quería la respuesta en PowerShell. Su respuesta fue instalar algo y usarlo. Que podría haber sugerido instalar Ruby, etc
SteveC