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

308

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

Ich habe aus mehreren Quellen erfahren, dass der offensichtlichste Befehl Remove-Item $targetDir -Recurse -Forcenicht richtig funktioniert. Dies beinhaltet eine Anweisung in der PowerShell V2-Onlinehilfe (gefunden mit 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 mithilfe des Pipeline-Operators an das Cmdlet Remove-Item ...

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

Ich suche nach dem saubersten Weg, ein ganzes Verzeichnis, Dateien und untergeordnete Verzeichnisse auszublasen, ohne Benutzerwarnmeldungen mit der geringsten Menge an Code zu generieren. Ein Einzeiler wäre schön, wenn es leicht zu verstehen wäre.

Matt Spradley
quelle
2
Powershell, ich weiß, aberRD /S /Q
Rubens Farias
Mögliches Duplikat: stackoverflow.com/questions/1667145/…
Rubens Farias
Ich denke nicht, dass es ein Duplikat ist. Ich habe 1667145 vor dem Posten überprüft. Es wird gefragt, warum PowerShell den Parameter Recurse bool nicht richtig einstellt, wenn die Implementierung der Remove-Item-Methode eines benutzerdefinierten PowerShell-Anbieters aufgerufen wird. Ich habe nach dem Verhalten von Remove-Item gefragt, da es sich auf den integrierten Dateisystemanbieter bezieht.
Matt Spradley
2
"RD / S / Q" scheint in PowerShell nicht zu funktionieren - sagt "Remove-Item: Es kann kein Positionsparameter gefunden werden, der das Argument '/ q' akzeptiert."
BrainSlugs83
5
rdist ein Alias ​​für Remove-Itemin Powershell. cmd /c "rd /s /q"funktioniert aber.
Codekaizen

Antworten:

510
Remove-Item -Recurse -Force some_dir

funktioniert in der Tat wie hier angegeben.

rm -r -fo some_dir

sind Kurzform-Aliase, die auch funktionieren.

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

Joey
quelle
5
Ich denke du bist richtig. Ich erhielt die Meldung "Das Element kann in einem Verzeichnis nicht entfernt werden, da es verwendet wird." Fehler und nahm an, dass es ein Problem mit dem Rekursionsalgorithmus war und suchte nach einer Problemumgehung. Es stellte sich heraus, dass ich einen Prozess hatte, den ich zuvor in dem Skript ausgelöst hatte, das im Zielverzeichnis arbeitete. Wenn das Skript geändert wird, um auf den anderen Prozess zu warten, funktioniert der Befehl "Remove-Item -Recurse -Force". Schau immer zuerst in den Spiegel :)
Matt Spradley
15
Ich habe festgestellt, dass ich dies zweimal ausführen muss, wenn es in einem Verzeichnis ausgeführt wird, das Unterverzeichnisse enthält. Beim ersten Mal treten viele Fehler "Das Verzeichnis ist nicht leer" auf. Das zweite Mal wird es ohne Fehler abgeschlossen.
Kristopher Johnson
5
Kristopher Johnson, ich erhalte ähnliche Fehler mit verschiedenen Tools unter Windows 7. Es scheint, dass der Löschaufruf früher zurückkehrt, als eine Datei oder ein Ordner tatsächlich entfernt wurde, was manchmal zu Problemen führt. Dies scheint in Explorer, Far, cmd und PowerShell zu geschehen.
Joey
2
@Joey "Es scheint, dass der Löschaufruf früher zurückkehrt, als eine Datei oder ein Ordner tatsächlich entfernt wurde, was manchmal zu Problemen führt." -> Zur Verdeutlichung: Der übergeordnete Ordner wird nicht gelöscht und es wird folgende Fehlermeldung angezeigt: "[übergeordneter Ordner] kann nicht entfernt werden, da er nicht leer ist." Ich sehe dies ständig auf (langsamen) vernetzten Laufwerken. Die einzige Lösung ist die alte: cmd /c rdwie unten angegeben.
Davor Josipovic
6
Was ist mit "Das Verzeichnis ist nicht leer" -Fehlern? serverfault.com/questions/199921/powershell-remove-force Vielleicht besser get-childitem * -include * .csv -recurse | Gegenstand entfernen, den ich nicht kenne. Siehe stackoverflow.com/a/1668471/206730
Kiquenet
39

Ich benutzte:

rm -r folderToDelete

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

Tuan Jinn
quelle
Benötigt das nicht Cygwin, Git oder ein anderes Tool, das eine Bash-Shell unter Windows simulieren kann?
Pete
19
@Pete, nein, es wird nur PowerShell benötigt. rmist ein Alias ​​für Remove-Itemin der Standardkonfiguration von PowerShell. Überprüfen Sie die Ausgabe von Get-Alias rmfür weitere Details. Das -rnutzt das teilweise Übereinstimmungsverhalten von PowerShell für Parameter. Da Remove-Itemnur der eine Parameter mit einem 'r' beginnt -Recurse, -rstimmt dieser überein. So funktioniert die folgend alle gleich: rm -r, rm -re,Remove-Item -Recurse . (Beachten Sie, dass weder rm -rfnoch rm -r -ffunktioniert, sondern rm -r -fowird. -rf-f
Entspricht
1
Wie wär es damit. Der Powershell rm-Alias ​​für "Remove-Item -Recurse -Force some_dir" funktioniert besser als die direkte Verwendung von remove-item. Ich habe die gleichen Fehler erhalten. "Das Element kann nicht in einem Verzeichnis entfernt werden. Ich wechsle ohne Fehler von" Element entfernen "zu" rm -r ".
Greg
Interessant. Ich habe Cygwin-Werkzeuge auf meiner Box und hatte es versuchtrm -rf folder und natürlich ist es fehlgeschlagen. Ich habe die Antwort zunächst abgelehnt (weil dort Ubuntu stand). Dank des Kommentars von @chwarr habe ich es ohne das versucht fund es hat den Alias ​​und nicht die rm-Binärdatei übernommen. Ich wünschte, Tuan würde seine Quelle aktualisieren (nicht sicher, ob Tuan wusste, dass es ein Alias ​​war oder wirklich dachte, es sei das Unix rm ;-)
Joshua Ball
2
Vielleicht liegt es daran, dass ich das -Ranstelle von verwende -r(obwohl PowerShell meines Wissens wie der Rest von Windows nicht zwischen Groß- und Kleinschreibung unterscheidet, daher sollte es keinen Unterschied machen), aber ich habe einen Fehler erhalten, dass die Ordner, die ich löschen möchte, sind nicht leer.
Rbaleksandar
25

Beim rekursiven Löschen von Dateien mit einer einfachen Datei wird Remove-Item "folder" -Recursemanchmal 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 Elemente mit, pspath -Descendingdamit die Blätter vor den Wurzeln gelöscht werden. Die Sortierung erfolgt nach dem pspathParameter, da dies eine größere Chance hat, für andere Anbieter als das Dateisystem zu arbeiten. Der -IncludeParameter 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
John Rees
quelle
1
Bei der Behebung eines Problems mit PowerShell in TFS-Build-Skripten erwies sich dies als die richtige Antwort.
Rcabr
Dies ist auch für mich die Lösung. Haben Sie einige Punkte, mein guter Mann!
Jammer
Hat für mich gearbeitet. Ich konnte den Inhalt eines Ordners nicht rekursiv löschen, aber Ihre Lösung hat bei mir funktioniert. danke
SheldonH
Dies ist eine sehr robuste Lösung
Max Young
Ich bin mir nicht sicher, warum die akzeptierte Antwort so viele Stimmen hat - ich persönlich erhalte immer noch zeitweise Fehler bei der Verwendung remove-item -recursein Powershell v5, daher ist diese Lösung am besten für mich.
JonoB
13
rm -r ./folder -Force    

... hat für mich gearbeitet

stevethecollier
quelle
11

Versuchen Sie dieses Beispiel. Wenn das Verzeichnis nicht vorhanden ist, 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
Steve
quelle
7

Verwenden Sie den DOS-Befehl der alten Schule:

rd /s <dir>
Peter Mortensen
quelle
Wenn dies Teil eines Skripts ist, müssten Sie auch verwenden /q(Ruhiger Modus, fragen Sie nicht, ob es in Ordnung ist, einen Verzeichnisbaum mit / S zu entfernen).
wildeyes
6

Aus irgendeinem Grund funktionierte John Rees 'Antwort in meinem Fall manchmal nicht. Aber es führte mich in die folgende Richtung. Zuerst versuche ich das Verzeichnis rekursiv mit der Option buggy -recurse 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
        }
    }
}
jdoose
quelle
Können Sie den Fehler reproduzieren, wenn Sie meine Funktionen ausführen? Ich würde gerne wissen, damit ich sie verbessern kann.
John Rees
Entschuldigung, erinnere mich nicht an die genaue Einstellung. : / Ich denke, es war, als mehrere Unterverzeichnisse beteiligt waren. Es kam vor, dass der Aufruf von "Remove-Item -force -recurse" nicht alle Dateien löschte und in diesem Fall der letzte Remove-Tree fehlschlug, weil das Verzeichnis nicht leer war. Aus diesem Grund habe ich mir die neue Lösung ausgedacht, um zuerst die fehlerhafte integrierte Version (-force) auszuprobieren und dann manuell in jedes Verzeichnis abzusteigen und "manuell" zu löschen, was noch übrig ist. Diese Version wird regelmäßig verwendet und funktioniert bis jetzt. Die einzige Ursache, die fehlgeschlagen ist, war, wenn ein Programm noch ein Handle für ein Verzeichnis enthält.
jdoose
5

Um die 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 Einfügen von Kopien lautet:

& cmd.exe /c rd /S /Q $folderToDelete
Dejan
quelle
3
Es gibt immer noch den Fehler "Das Verzeichnis ist nicht leer" für Ordner!?
Oncel Umut TURER
2

Ich habe einen anderen Ansatz gewählt, der von @ john-rees oben inspiriert wurde - besonders als sein Ansatz irgendwann für mich zu scheitern begann. Verwenden Sie den Teilbaum grundsätzlich und sortieren Sie 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 ist hier eine weitere Gotchya, die Sie möglicherweise trifft: https://superuser.com/q/212808

Peter McEvoy
quelle
2
del <dir> -Recurse -Force # I prefer this, short & sweet

ODER

remove-item <dir> -Recurse -Force

Wenn Sie ein riesiges Verzeichnis haben, mache ich das normalerweise

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

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

Gajendra D Ambi
quelle
Ich gebe zu, dass Ihre Idee mit der Überwachung nützlich sein kann, aber sie unterscheidet sich kaum davon, eine Nachricht nur zu drucken, wenn sie fertig ist, und falls es Probleme beim Stoppen des Remove-Elements gab, wird Ihre Schleife niemals enden.
Raúl Salinas-Monteagudo
@ RaúlSalinas-Monteagudo stimmt, aber es ist definitiv für ein Produkt oder ein unbeaufsichtigtes Anwendungsfall-Szenario. Es muss klein genug sein, damit sich jemand unterwegs nur daran erinnert und tippt und keine anspruchsvolle .ps1-Datei nur in einem Verzeichnis ausführt.
Gajendra D Ambi
2

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 "Zugriff verweigert" oder "Nicht autorisierter Zugriff" führen. Ich weiß nicht, warum dies passiert, obwohl aus diesem StackOverflow-Beitrag einige Erkenntnisse gewonnen werden können .

Ich konnte diese Probleme umgehen, indem ich die Reihenfolge festlegte, in der Elemente im Ordner gelöscht werden, und Verzögerungen hinzufügte. Folgendes läuft gut für mich:

# 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 mit berechneten Eigenschaften in PowerShell war hilfreich, um eine Liste der Unterordner nach Tiefe zu sortieren.

Ähnliche Zuverlässigkeitsprobleme mit RD / S / Q können gelöst werden, indem DEL / F / S / Q vor RD / S / Q ausgeführt und der RD bei Bedarf ein zweites Mal ausgeführt wird - idealerweise mit einer Pause dazwischen (dh mit Ping wie gezeigt) unten).

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

Ganz einfach:

remove-item -path <type in file or directory name>, press Enter
DusanV
quelle
Sie sollten auch eine Beispielausführung anbieten.
unteilbar
1

Ein weiterer nützlicher Trick:

Wenn Sie viele Dateien mit derselben oder einer ähnlichen Namenskonvention finden (wie eine Mac-Datei mit einem Punktpräfixnamen ... diese berühmte Datei), können Sie sie 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.

Daniel Alberto Lepe Ayala
quelle
Warum nicht verwenden rm -rf .*? Ich habe keine Powershell zum Testen, aber ich denke, es wird funktionieren.
Vini.g.fer
1
Es ist einfach; Wenn Sie nur "| rm" aus dem Befehl entfernen, können Sie ein ganzes Panorama dessen anzeigen, was Sie löschen möchten, nachdem Sie sicher waren, dass Sie den Befehl ausführen können.
Daniel Alberto Lepe Ayala
Por cierto, para quitar los archivos que empiecen con punto, (como los de mac) pero que tengan propiedad de oculto, puedes usar: ls -r -h. * | rm
Daniel Alberto Lepe Ayala
1

Verwenden Sie zum Löschen des gesamten Inhalts einschließlich der Ordnerstruktur

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

Das -recurseHinzufügen zu remove-itemstellt sicher, dass interaktive Eingabeaufforderungen deaktiviert sind.

Steve Simon
quelle
-1
$users = get-childitem \\ServerName\c$\users\ | select -ExpandProperty name

foreach ($user in $users)

{
remove-item -path "\\Servername\c$\Users\$user\AppData\Local\Microsoft\Office365\PowerShell\*" -Force -Recurse
Write-Warning "$user Cleaned"
}

Schrieb das Obige, um einige Protokolldateien zu bereinigen, ohne das übergeordnete Verzeichnis zu löschen, und dies funktioniert perfekt!

Tom Stevenson
quelle
-2
rm -r <folder_name>
c:\>rm -r "my photos"
user3008
quelle
1
Bitte erklären Sie dies weiter, damit andere aus Ihrer Antwort lernen können
Nico Haase