it-swarm.com.de

Wie lösche ich rekursiv ein gesamtes Verzeichnis mit PowerShell 2.0?

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

Ich habe aus mehreren Quellen gelernt, dass der offensichtlichste Befehl, Remove-Item $targetDir -Recurse -Force funktioniert nicht richtig. Dies beinhaltet eine Anweisung in der PowerShell V2-Online-Hilfe (gefunden mit Get-Help Remove-Item -Examples) das besagt:

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

Ich habe verschiedene Beispiele gesehen, die Get-ChildItem verwenden und an Remove-Item weiterleiten, aber die Beispiele entfernen normalerweise einige Dateigruppen basierend auf einem Filter, nicht das gesamte Verzeichnis .

Ich suche nach der saubersten Methode, um ein gesamtes Verzeichnis, Dateien und untergeordnete Verzeichnisse auszublasen, ohne dass Benutzerwarnmeldungen mit der geringsten Menge an Code generiert werden. Ein Einzeiler wäre schön, wenn er leicht zu verstehen wäre.

254
Matt Spradley
Remove-Item -Recurse -Force some_dir

funktioniert ja so wie hier geworben.

rm -r -fo some_dir

sind Abkürzungen, die auch funktionieren.

Soweit ich es verstanden habe, funktioniert der Parameter -Recurse Einfach nicht richtig, wenn Sie versuchen, einen gefilterten Satz von Dateien rekursiv zu löschen. Um ein einziges Verzeichnis und alles darunter zu töten, scheint es gut zu funktionieren.

433
Joey

Ich benutzte:

rm -r folderToDelete

Das funktioniert für mich wie ein Zauber (ich habe es Ubuntu gestohlen).

37
Tuan Jinn

Beim rekursiven Löschen von Dateien mit einem einfachen Remove-Item "folder" -Recurse Wird manchmal ein zeitweiliger Fehler angezeigt: [folder] cannot be removed because it is not empty.

Diese Antwort versucht, diesen Fehler zu verhindern, indem die Dateien einzeln gelöscht werden.

function Get-Tree($Path,$Include='*') { 
    @(Get-Item $Path -Include $Include -Force) + 
        (Get-ChildItem $Path -Recurse -Include $Include -Force) | 
        sort pspath -Descending -unique
} 

function Remove-Tree($Path,$Include='*') { 
    Get-Tree $Path $Include | Remove-Item -force -recurse
} 

Remove-Tree some_dir

Ein wichtiges Detail ist die Sortierung aller Artikel mit pspath -Descending, Damit die Blätter vor den Wurzeln gelöscht werden. Die Sortierung erfolgt nach dem Parameter pspath, da dies die Chance erhöht, für andere Anbieter als das Dateisystem zu arbeiten. Der Parameter -Include Ist nur eine Annehmlichkeit, wenn Sie die zu löschenden Elemente filtern möchten.

Es ist in zwei Funktionen unterteilt, da ich es nützlich finde, zu sehen, was ich durch Ausführen löschen möchte

Get-Tree some_dir | select fullname
23
John Rees
rm -r ./folder -Force    

... hat für mich gearbeitet

9
stevethecollier

Probieren Sie dieses Beispiel aus. Wenn das Verzeichnis nicht existiert, wird kein Fehler ausgelöst. Möglicherweise benötigen Sie PowerShell v3.0.

remove-item -path "c:\Test Temp\Test Folder" -Force -Recurse -ErrorAction SilentlyContinue
9
steve

Verwenden Sie den alten DOS-Befehl:

rd /s <dir>
8
Anonymous

Um den Fehler "Das Verzeichnis ist nicht leer" der akzeptierten Antwort zu vermeiden, verwenden Sie einfach den guten alten DOS-Befehl, wie zuvor vorgeschlagen. Die vollständige PS-Syntax zum Kopieren und Einfügen lautet:

& cmd.exe /c rd /S /Q $folderToDelete
6
Dejan

Aus irgendeinem Grund funktionierte die Antwort von John Rees in meinem Fall manchmal nicht. Aber es hat mich in die folgende Richtung geführt. Zuerst versuche ich, das Verzeichnis mit der Option buggy -recurse rekursiv zu löschen. Danach gehe ich in jedes verbleibende Unterverzeichnis und lösche alle Dateien.

function Remove-Tree($Path)
{ 
    Remove-Item $Path -force -Recurse -ErrorAction silentlycontinue

    if (Test-Path "$Path\" -ErrorAction silentlycontinue)
    {
        $folders = Get-ChildItem -Path $Path –Directory -Force
        ForEach ($folder in $folders)
        {
            Remove-Tree $folder.FullName
        }

        $files = Get-ChildItem -Path $Path -File -Force

        ForEach ($file in $files)
        {
            Remove-Item $file.FullName -force
        }

        if (Test-Path "$Path\" -ErrorAction silentlycontinue)
        {
            Remove-Item $Path -force
        }
    }
}
5
jdoose

Ich habe einen anderen Ansatz gewählt, der von @ john-rees inspiriert war - besonders, als sein Ansatz irgendwann für mich scheiterte. Grundsätzlich den Teilbaum rekursiv bearbeiten und die Dateien nach ihrer Pfadlänge sortieren - vom längsten zum kürzesten löschen

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 ist hier ein weiteres Fallbeispiel, das Sie möglicherweise trifft: https://superuser.com/q/212808

2
Peter McEvoy

Das Löschen eines gesamten Ordnerbaums funktioniert manchmal und schlägt manchmal mit den Fehlern "Verzeichnis nicht leer" fehl. Der anschließende Versuch, zu überprüfen, ob der Ordner noch vorhanden ist, kann zu Fehlern wie "Zugriff verweigert" oder "Nicht autorisierter Zugriff" führen. Ich weiß nicht, warum dies geschieht, obwohl einige Erkenntnisse aus dieser StackOverflow-Veröffentlichung gewonnen werden können.

Ich konnte diese Probleme umgehen, indem ich die Reihenfolge festlegte, in der Elemente im Ordner gelöscht werden, und indem ich Verzögerungen hinzufügte. Folgendes läuft für mich 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 sing Calculated Properties in PowerShell war hilfreich, um eine nach Tiefe sortierte Liste der Unterordner zu erhalten.

Ähnliche Zuverlässigkeitsprobleme mit RD/S/Q können durch zweimaliges Ausführen von RD/S/Q gelöst werden - idealerweise mit einer Pause dazwischen (dh mit ping wie unten gezeigt).

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
1
MikeOnline

Ganz einfach:

remove-item -path <type in file or directory name>, press Enter
1
DusanV

Um den gesamten Inhalt einschließlich der Ordnerstruktur zu löschen, verwenden Sie

get-childitem $dest -recurse | foreach ($_) {remove-item $_.fullname -recurse}

Das -recurse hinzugefügt zu remove-item stellt sicher, dass interaktive Eingabeaufforderungen deaktiviert sind.

1
steve simon
del <dir> -Recurse -Force # I prefer this, short & sweet

OR

remove-item <dir> -Recurse -Force

Wenn Sie ein riesiges Verzeichnis haben, ist das, was ich normalerweise tue

while (dir | where name -match <dir>) {write-Host deleting; sleep -s 3}

Führen Sie dies auf einem anderen Powershell-Terminal aus und es stoppt, wenn es fertig ist.

1
Gajendra D Ambi

Ein weiterer nützlicher Trick:

Wenn Sie viele Dateien mit der gleichen oder einer ähnlichen Namenskonvention finden (wie eine Mac-Datei mit dem Punkt-Präfix-Namen ... diese berühmte Dateiauswahl), können Sie diese einfach mit einer einzigen Zeile aus der PowerShell entfernen:

ls -r .* | rm

In dieser Zeile werden alle Dateien mit einem Punkt am Anfang des Namens im aktuellen Verzeichnis und alle Dateien mit denselben Umständen auch in anderen Ordnern in diesem Verzeichnis entfernt. Seien Sie sich dessen bewusst, wenn Sie es verwenden. : D