Durchlaufen Sie Dateien in einem Verzeichnis mit PowerShell

243

Wie kann ich den folgenden Code ändern, um alle .log-Dateien im Verzeichnis und nicht nur die eine Datei anzuzeigen?

Ich muss alle Dateien durchlaufen und alle Zeilen löschen, die nicht "step4" oder "step9" enthalten. Derzeit wird dadurch eine neue Datei erstellt, aber ich bin mir nicht sicher, wie ich die for eachSchleife hier verwenden soll (Neuling).

Die tatsächlichen Dateien heißen wie folgt : 2013 09 03 00_01_29.log . Ich möchte, dass die Ausgabedateien sie entweder überschreiben oder den gleichen Namen mit "out" anhängen.

$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
user2725402
quelle

Antworten:

363

Probieren Sie es aus:

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
quelle
Vielen Dank. Der BaseName-Teil funktioniert nicht (Version 1) - aber ich habe es geschafft, indem ich zuerst eine Sicherung der vollständigen Datei erstellt und dann die Änderung an der Originaldatei vorgenommen habe.
user2725402
6
Für v1 können Sie den Basisnamen wie folgt extrahieren: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy
Wenn ich ersetzen BaseNamemit FullNameich bekommen , was ich will.
M--
77

Um den Inhalt eines Verzeichnisses abzurufen, können Sie verwenden

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

Dann können Sie auch diese Variable durchlaufen:

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
}

Ein noch einfacherer Weg, dies foreachauszudrücken, ist die Schleife (dank @Soapy und @MarkSchultheiss):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}
PVitt
quelle
Dadurch wird eine Ausgabedatei mit dem Namen "out.log" erstellt. Wie kann ich für jede Eingabedatei eine eigene Ausgabedatei erstellen?
user2725402
@ user2725402 Ich habe eine eingabeabhängige Ausgabedatei mit dem Namen <Eingabedateiname> out
hinzugefügt
Ich bin mir nicht sicher, was ich falsch mache, aber das funktioniert nicht. Ich erhalte jetzt keine Ausgabedateien (und keine Fehler): $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
Sie können auch tunforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy
1
oder verwendenForEach ($f in $files){...}
Mark Schultheiss
31

Wenn Sie eine rekursive Schleife in einem Verzeichnis für einen bestimmten Dateityp durchführen müssen, verwenden Sie den folgenden Befehl, der alle Dateien des docDateityps filtert

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

Wenn Sie die Filterung für mehrere Typen durchführen müssen, verwenden Sie den folgenden Befehl.

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

Jetzt $fileNamesfungieren Variablen als Arrays, aus denen Sie Ihre Geschäftslogik schleifen und anwenden können.

Sarath Avanavu
quelle
Was mich nervte, war das Weglassen von versteckten und / oder Systemdateien. Um sie auch zu sehen, müssen Sie den -ForceParameter Get-ChildItem verwenden. Siehe das Dokument unter docs.microsoft.com/en-us/powershell/module/… .
til_b
-6

Andere Antworten sind großartig, ich möchte nur hinzufügen ... einen anderen Ansatz, der in PowerShell verwendet werden kann: Installieren Sie GNUWin32-Dienstprogramme und verwenden Sie grep, um die Zeilen anzuzeigen / die Ausgabe in die Datei http://gnuwin32.sourceforge.net/ umzuleiten.

Dadurch wird die neue Datei jedes Mal überschrieben:

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

Dadurch wird die Protokollausgabe angehängt, falls Sie die Anmeldedatei überschreiben und die Daten behalten möchten:

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

Hinweis: Um GNUWin32-Utils global verwenden zu können, müssen Sie den Ordner bin zu Ihrem Systempfad hinzufügen.

user1628658
quelle
18
Diese Frage wurde als PowerShell markiert, nicht als Unix
SteveC
2
Ja. Offensichtlich. Meine Einstellung war ziemlich einfach: Sie können GNUWin32-Dienstprogramme in Windows verwenden, daher können Sie * nix-Tools in Powershell problemlos verwenden. Funktioniert. Niemand hat jemals gesagt, dass die Antwort vollständig von Powershell stammen muss. Und selbst wenn ja, können Sie Win32 Utils direkt von Powershell aus aufrufen. AFAIK mit allem, was verfügbar und kompatibel ist, ist eigentlich keine schlechte Sache.
user1628658
2
Ich hätte meinen vorherigen Kommentar bearbeitet, aber ich habe das 5-Minuten-Limit überschritten: SteveC: Wollen Sie damit sagen, dass die Integration von GNU-Tools, die unter Windows einwandfrei funktionieren, Powershell irgendwie trotzt? Das ist eine Sache. Ich verstehe, dass es kurzfristig produktiver sein könnte, dies nur in Powershell zu erarbeiten. Langfristig hat die Erweiterung der Möglichkeiten tatsächlich mehr Wert. Sie fügen weitere Optionen hinzu und arbeiten vollständig in Windows und Powershell ohne Linux-Emulatoren wie Cygwin. Obwohl ich Ihre Reservierung verstehe, bin ich anderer Meinung.
user1628658
5
Bei der Frage ging es darum, in PowerShell zu suchen, nicht um die Vielzahl anderer Sprachen, die verwendet werden könnten.
SteveC
1
Antworten sollen auf die Frage sein. Diese Frage war insofern explizit, als sie die Antwort in PowerShell wollte. Ihre Antwort war, etwas zu installieren und zu verwenden. Sie hätten vorschlagen können, Ruby usw. zu installieren
SteveC