Scorri i file in una directory usando PowerShell


243

Come posso modificare il seguente codice per guardare tutti i file .log nella directory e non solo un file?

Devo scorrere tutti i file ed eliminare tutte le righe che non contengono "step4" o "step9". Attualmente questo creerà un nuovo file, ma non sono sicuro di come utilizzare il for eachloop qui (newbie).

I file effettivi sono denominati in questo modo: 2013 09 03 00_01_29.log . Vorrei che i file di output li sovrascrivessero o che avessero il nome SAME, aggiunto 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

Risposte:


363

Prova questo:

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')
}

Grazie. La parte BaseName non funziona (versione 1), ma sono riuscito prima creando un backup del file completo, quindi apportando la modifica al file originale.
user2725402,

6
Per v1, è possibile utilizzare quanto segue per estrarre il nome di base: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy,

Se sostituisco BaseNamecon FullNameottengo quello che voglio.
M--

78

Per ottenere il contenuto di una directory è possibile utilizzare

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

Quindi è possibile eseguire il ciclo anche su questa variabile:

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
}

Un modo ancora più semplice per dirlo è il foreachloop (grazie a @Soapy e @MarkSchultheiss):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Questo crea un file di output chiamato "out.log". Come posso creare un file di output separato per ciascun file di input?
user2725402,

@ user2725402 Ho aggiunto un file di output dipendente dall'input che si chiama <nome file input> out
PVitt

non sono sicuro di cosa sto facendo di sbagliato, ma questo non funziona - Ora non ottengo alcun file di output (e nessun errore): $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
Puoi anche farloforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy,

1
o utilizzareForEach ($f in $files){...}
Mark Schultheiss,

31

Se è necessario eseguire il ciclo ricorsivo all'interno di una directory per un particolare tipo di file, utilizzare il comando seguente, che filtra tutti i file di doctipo file

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

Se è necessario eseguire il filtraggio su più tipi, utilizzare il comando seguente.

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

Ora le $fileNamesvariabili fungono da array da cui è possibile eseguire il loop e applicare la logica aziendale.


Ciò che mi ha infastidito è stata l'omissione di file nascosti e / o di sistema. Per vederli anche devi usare il -Forceparametro per Get-ChildItem. Vedi il suo documento su docs.microsoft.com/en-us/powershell/module/… .
fino

-6

Altre risposte sono ottime, voglio solo aggiungere ... un diverso approccio utilizzabile in PowerShell: installa GNUWin32 utils e usa grep per visualizzare le linee / reindirizzare l'output sul file http://gnuwin32.sourceforge.net/

Questo sovrascrive il nuovo file ogni volta:

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

Ciò accoda l'output del registro, nel caso in cui si sovrascriva il file di accesso e si desideri conservare i dati:

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

Nota: per poter utilizzare le utility GNUWin32 a livello globale, è necessario aggiungere la cartella bin al percorso di sistema.


18
Questa domanda è stata etichettata come PowerShell, non Unix
SteveC

2
Sì. Ovviamente. La mia opinione era abbastanza semplice: puoi usare le utility GNUWin32 in Windows, quindi puoi usare facilmente gli strumenti * nix in Powershell. Lavori. Nessuno ha mai detto che la risposta doveva essere interamente nativa di Powershell. E anche se lo facessero, puoi ancora chiamare Win32 Utils direttamente da Powershell. AFAIK che utilizza tutto ciò che è disponibile e compatibile non è in realtà una cosa negativa.
user1628658

2
Avrei modificato il mio commento precedente, ma ho superato il limite di 5 minuti: SteveC: Stai dicendo che incorporare strumenti GNU che funzionano bene con Windows sta in qualche modo sfidando Powershell? Questa è una cosa. Capisco che risolverlo puramente in Powershell potrebbe essere più produttivo a breve termine. A lungo termine, le possibilità hanno effettivamente più merito. Aggiungete più opzioni e state lavorando interamente in Windows e Powershell senza emulatori Linux come Cygwin. Quindi, mentre capisco la tua prenotazione, non sono d'accordo.
user1628658

5
La domanda riguardava la ricerca in PowerShell, non la moltitudine di altre lingue che potevano essere utilizzate.
SteveC,

1
Le risposte sono pensate per essere alla domanda. Questa domanda era esplicita in quanto voleva la risposta in PowerShell. La tua risposta è stata installare qualcosa e usarlo. Avresti potuto suggerire di installare Ruby, ecc.
SteveC
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.