web-dev-qa-db-fra.com

Comment supprimer récursivement un répertoire entier avec PowerShell 2.0?

Quel est le moyen le plus simple de supprimer de force un répertoire et tous ses sous-répertoires dans PowerShell? J'utilise PowerShell V2 sous Windows 7.

J'ai appris de plusieurs sources que la commande la plus évidente, Remove-Item $targetDir -Recurse -Force, ne fonctionne pas correctement. Cela inclut une déclaration dans l'aide en ligne de PowerShell V2 (trouvée à l'aide de Get-Help Remove-Item -Examples) qui indique:

... car le paramètre Recurse de cette cmdlet est défectueux, la commande utilise la cmdlet Get-Childitem pour obtenir les fichiers souhaités, et elle utilise l'opérateur de pipeline pour les transmettre à la cmdlet Remove-Item ...

J'ai vu divers exemples utilisant Get-ChildItem et le diriger vers Remove-Item, mais les exemples suppriment généralement certains ensembles de fichiers basés sur un filtre, et non le répertoire entier. .

Je cherche le moyen le plus propre de supprimer tout un répertoire, des fichiers et des répertoires enfants, sans générer de message d'avertissement à l'aide d'un minimum de code. Un one-line serait bien s'il est facile à comprendre.

254
Matt Spradley
Remove-Item -Recurse -Force some_dir

fonctionne effectivement comme annoncé ici.

rm -r -fo some_dir

sont des alias de sténographie qui fonctionnent aussi.

Autant que je sache, le paramètre -Recurse ne fonctionne tout simplement pas correctement lorsque vous essayez de supprimer un ensemble filtré de fichiers de manière récursive. Pour tuer un seul répertoire et tout ce qui se trouve en dessous, cela semble bien fonctionner.

433
Joey

J'ai utilisé:

rm -r folderToDelete

Cela fonctionne pour moi comme un charme (je l'ai volé à Ubuntu).

37
Tuan Jinn

Lors de la suppression récursive de fichiers à l'aide d'un simple Remove-Item "folder" -Recurse, une erreur intermittente apparaît parfois: [folder] cannot be removed because it is not empty.

Cette réponse tente d'éviter cette erreur en supprimant individuellement les fichiers.

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

Un détail important est le tri de tous les éléments avec pspath -Descending afin que les feuilles soient supprimées avant les racines. Le tri s'effectue sur le paramètre pspath car il a plus de chance de fonctionner pour des fournisseurs autres que le système de fichiers. Le paramètre -Include n'est utile que si vous souhaitez filtrer les éléments à supprimer.

Il est divisé en deux fonctions car je trouve utile de voir ce que je suis sur le point de supprimer en exécutant

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

... a travaillé pour moi

9
stevethecollier

Essayez cet exemple. Si le répertoire n'existe pas, aucune erreur n'est générée. Vous aurez peut-être besoin de PowerShell v3.0.

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

Utilisez la commande DOS old-school:

rd /s <dir>
8
Anonymous

Pour éviter les erreurs "Le répertoire n'est pas vide" de la réponse acceptée, utilisez simplement la bonne vieille commande DOS comme suggéré précédemment. La syntaxe PS complète prête au copier-coller est la suivante:

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

Pour une raison quelconque, la réponse de John Rees n'a parfois pas fonctionné dans mon cas. Mais cela m'a conduit dans la direction suivante. J'essaie d'abord de supprimer le répertoire de manière récursive avec l'option buggy -recurse. Ensuite, je descends dans chaque sous-répertoire qui reste et supprime tous les fichiers.

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

J'ai adopté une autre approche inspirée par @ john-rees ci-dessus - en particulier lorsque son approche a commencé à échouer pour moi à un moment donné. En résumé, ré-infirmer la sous-arborescence et trier les fichiers en fonction de leur longueur de chemin - supprimer du plus long au plus court

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

En ce qui concerne la magie -LiteralPath, voici un autre gotchya qui pourrait vous frapper: https://superuser.com/q/212808

2
Peter McEvoy

La suppression d'une arborescence de dossiers complète fonctionne parfois et échoue parfois avec des erreurs "Le répertoire n'est pas vide". Toute tentative ultérieure de vérifier si le dossier existe toujours peut entraîner des erreurs "Accès refusé" ou "Accès non autorisé". Je ne sais pas pourquoi cela se produit, même si certaines informations peuvent être tirées de cette publication StackOverflow .

J'ai pu résoudre ces problèmes en spécifiant l'ordre dans lequel les éléments du dossier sont supprimés et en ajoutant des délais. Ce qui suit fonctionne bien pour moi:

# 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

Un article Microsoft TechNet tilisation des propriétés calculées dans PowerShell m'a été utile pour obtenir une liste de sous-dossiers triés par profondeur.

Des problèmes de fiabilité similaires avec RD/S/Q peuvent être résolus en exécutant RD/S/Q deux fois - idéalement avec une pause entre (c'est-à-dire en utilisant un ping comme indiqué ci-dessous).

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

Vraiment simple:

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

Pour supprimer le contenu complet, y compris la structure de dossiers, utilisez

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

Le -recurse ajouté à remove-item garantit que les invites interactives sont désactivées.

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

OR

remove-item <dir> -Recurse -Force

Si vous avez un énorme répertoire, ce que je fais habituellement est

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

Exécutez ceci sur un autre terminal powershell et il s’arrêtera à la fin.

1
Gajendra D Ambi

n autre truc utile:

Si vous trouvez beaucoup de fichiers avec une convention de nom identique ou similaire (comme un fichier mac avec un nom de préfixe de point ... ce fameux pull de fichier), vous pouvez facilement les supprimer en une seule ligne comme suit:

ls -r .* | rm

Cette ligne va supprimer tous les fichiers avec un point au début du nom dans le répertoire en cours, ainsi que tous les fichiers avec les mêmes circonstances dans d'autres dossiers à l'intérieur de ce répertoire. Soyez conscient lorsque vous l'utilisez. :RÉ