495 Stimmen

Wie wird ein ganzes Verzeichnis mit PowerShell 2.0 rekursiv gelöscht?

Was ist die einfachste Methode, um ein Verzeichnis und alle seine Unterverzeichnisse in PowerShell zu löschen? Ich verwende PowerShell V2 unter Windows 7.

Ich habe aus verschiedenen Quellen erfahren, dass der offensichtlichste Befehl, Remove-Item $targetDir -Recurse -Force funktioniert nicht richtig. Dazu gehört auch eine Aussage in der PowerShell V2-Online-Hilfe (zu finden über Get-Help Remove-Item -Examples ), die besagt:

...Da der Recurse-Parameter in diesem Cmdlet fehlerhaft ist, verwendet der Befehl das Cmdlet "Get-Childitem", um die gewünschten Dateien abzurufen, und übergibt sie mit dem Pipelineoperator an das Cmdlet "Remove-Item"...

Ich habe verschiedene Beispiele gesehen, die Folgendes verwenden Get-ChildItem und leiten es an Entfernen-Element aber die Beispiele entfernen in der Regel eine Reihe von Dateien auf der Grundlage eines Filters, nicht das gesamte Verzeichnis.

Ich bin auf der Suche nach dem saubersten Weg, um ein ganzes Verzeichnis, Dateien und untergeordnete Verzeichnisse auszublasen, ohne irgendwelche Benutzerwarnungen zu generieren und dabei so wenig Code wie möglich zu verwenden. Ein Einzeiler wäre schön, wenn er leicht zu verstehen ist.

4voto

MikeOnline Punkte 731

Das Löschen eines gesamten Ordnerbaums funktioniert manchmal und schlägt manchmal mit der Fehlermeldung "Verzeichnis nicht leer" fehl. Der anschließende Versuch, zu überprüfen, ob der Ordner noch existiert, kann zu den Fehlern "Zugriff verweigert" oder "Unberechtigter Zugriff" führen. Ich weiß nicht, warum dies der Fall ist, aber vielleicht können Sie einen Einblick erhalten, wenn Sie dieser StackOverflow-Beitrag .

Ich konnte diese Probleme umgehen, indem ich die Reihenfolge festlegte, in der die Elemente innerhalb des Ordners gelöscht werden, und indem ich Verzögerungen hinzufügte. Die folgende Vorgehensweise funktioniert bei mir gut:

# First remove any files in the folder tree
Get-ChildItem -LiteralPath $FolderToDelete -Recurse -Force | Where-Object { -not ($_.psiscontainer) } | Remove-Item –Force

# Then remove any sub-folders (deepest ones first).    The -Recurse switch may be needed despite the deepest items being deleted first.
ForEach ($Subfolder in Get-ChildItem -LiteralPath $FolderToDelete -Recurse -Force | Select-Object FullName, @{Name="Depth";Expression={($_.FullName -split "\\").Count}} | Sort-Object -Property @{Expression="Depth";Descending=$true}) { Remove-Item -LiteralPath $Subfolder.FullName -Recurse -Force }

# Then remove the folder itself.  The -Recurse switch is sometimes needed despite the previous statements.
Remove-Item -LiteralPath $FolderToDelete -Recurse -Force

# Finally, give Windows some time to finish deleting the folder (try not to hurl)
Start-Sleep -Seconds 4

Ein Microsoft TechNet-Artikel Berechnete Eigenschaften verwenden in PowerShell war für mich hilfreich, um eine nach Tiefe sortierte Liste von Unterordnern zu erhalten.

Ähnliche Zuverlässigkeitsprobleme mit RD /S /Q kann gelöst werden, indem man DEL /F /S /Q vor RD /S /Q und die Ausführung der RD gegebenenfalls ein zweites Mal - idealerweise mit einer Pause dazwischen (d. h. mit ping wie unten dargestellt).

DEL /F /S /Q "C:\Some\Folder\to\Delete\*.*" > nul
RD /S /Q "C:\Some\Folder\to\Delete" > nul
if exist "C:\Some\Folder\to\Delete"  ping -4 -n 4 127.0.0.1 > nul
if exist "C:\Some\Folder\to\Delete"  RD /S /Q "C:\Some\Folder\to\Delete" > nul

3voto

Sergey Kostrukov Punkte 1107

Hinzufügen einer benutzerdefinierten Funktion in Ihrer PowerShell $profile :

function rmrf([string]$Path) {
    try {
        Remove-Item -Recurse -ErrorAction:Stop $Path
    } catch [System.Management.Automation.ItemNotFoundException] {
        # Ignore
        $Error.Clear()
    }
}

Dies ist die genaueste Darstellung der rm -rf Verhalten.

3voto

OSH Punkte 2647

Während rm -r gute Ergebnisse liefert, ist die folgende Methode schneller:

$fso = New-Object -ComObject scripting.filesystemobject
$fso.DeleteFolder("D:\folder_to_remove")

Um dies zu testen, können Sie einfach einen Ordner mit X Dateien erstellen (ich habe verwendet: Disketten-Tools um die Dateien schnell zu erstellen).

Und dann führen Sie jede der Varianten mit aus:

Measure-Command {rm D:\FOLDER_TO_DELETE -r}
Measure-Command {Remove-Item -Path D:\FOLDER_TO_DELETE -Recurse -Force}
Measure-Command {rd -r FOLDER_TO_DELETE }
$fso.DeleteFolder("D:\folder_to_remove")
Measure-Command {$fso.DeleteFolder("D:\FOLDER_TO_DELETE")}

waren die Ergebnisse in meinem Testordner:

Remove-Item - TotalMilliseconds : 1438.708
rm - TotalMilliseconds : 1268.8473
rd - TotalMilliseconds : 739.5385
FSO - TotalMilliseconds : 676.8091

Die Ergebnisse variieren, aber auf meinem System war der Gewinner das fileSystemObject. Ich empfehle, dies auf dem Zieldateisystem zu testen, um festzustellen, welche Methode für Sie die beste ist.

3voto

David Faivre Punkte 2232

Es scheint Probleme zu geben, bei denen Remove-Item -Force -Recurse kann unter Windows gelegentlich fehlschlagen, da das zugrunde liegende Dateisystem asynchron ist. Diese Antwort scheint das Problem zu lösen. Der Benutzer hat auch aktiv mit dem Powershell-Team zusammengearbeitet auf GitHub .

3voto

Peter McEvoy Punkte 2716

Ich habe einen anderen Ansatz gewählt, der von @john-rees oben inspiriert wurde - vor allem, als sein Ansatz bei mir irgendwann zu scheitern begann. Grundsätzlich rekursieren Sie den Teilbaum und sortieren die Dateien nach ihrer Pfadlänge - löschen Sie vom längsten zum kürzesten

Get-ChildItem $tfsLocalPath -Recurse |  #Find all children
    Select-Object FullName,@{Name='PathLength';Expression={($_.FullName.Length)}} |  #Calculate the length of their path
    Sort-Object PathLength -Descending | #sort by path length descending
    %{ Get-Item -LiteralPath $_.FullName } | 
    Remove-Item -Force

In Bezug auf die -LiteralPath Magie, hier ist ein weiterer gotchya, die Sie treffen können: https://superuser.com/q/212808

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X