Comment supprimer récursivement un répertoire entier avec PowerShell 2.0?
-
20-09-2019 - |
Question
Quelle est la façon la plus simple de supprimer avec force un répertoire et tous ses sous-répertoires dans PowerShell? J'utilise PowerShell V2 dans Windows 7.
Je l'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 PowerShell V2 (trouvé en utilisant Get-Help Remove-Item -Examples
) qui indique:
... Parce que le paramètre Recurse dans cette applet de commande est défectueuse, la commande utilise la commande Get-Childitem cmdlet pour obtenir les fichiers désirés, et il utilise pour les transmettre à l'opérateur de pipeline à l'applet de commande Remove-Item ...
Je l'ai vu plusieurs exemples qui utilisent Get-ChildItem et le tuyau à Remove-Item , mais les exemples supprimer généralement un ensemble de fichiers basé sur un filtre, non le répertoire entier.
Je cherche la façon la plus propre à souffler un répertoire entier, les fichiers et les répertoires enfants, sans générer des messages d'avertissement de l'utilisateur en utilisant le moins de code. serait bien en une ligne si elle est facile à comprendre.
La solution
Remove-Item -Recurse -Force some_dir
ne fonctionne en effet comme annoncé ici.
rm -r -fo some_dir
sont des alias sténographie qui fonctionnent aussi.
Pour autant que je compris, le paramètre -Recurse
ne fonctionne tout simplement lorsque vous essayez fonctionne pas correctement la suppression d'un ensemble filtré de fichiers récursive. Pour tuer un seul répertoire et tout en dessous semble fonctionner très bien.
Autres conseils
je:
rm -r folderToDelete
Cela fonctionne pour moi comme un charme (je l'ai volé de Ubuntu).
Lors de la suppression des fichiers en utilisant récursive simple Remove-Item "folder" -Recurse
je vois parfois une erreur intermittente: [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 sont effacées avant que les racines. Le tri se fait sur le paramètre pspath
depuis qui a plus de chance de travailler pour les fournisseurs autres que le système de fichiers. Le paramètre -Include
est juste une commodité si vous souhaitez filtrer les éléments à supprimer.
Il est divisé en deux fonctions que je trouve utile de voir ce que je suis sur le point de supprimer en exécutant
Get-Tree some_dir | select fullname
rm -r ./folder -Force
... travaillé pour moi
Essayez cet exemple. Si le répertoire n'existe pas, aucune erreur est soulevée. Vous devrez peut-être PowerShell v3.0.
remove-item -path "c:\Test Temp\Test Folder" -Force -Recurse -ErrorAction SilentlyContinue
Utilisez l'ancienne école commande DOS:
rd /s <dir>
Pour éviter le « Le répertoire est pas vide » erreurs de la réponse acceptée, il suffit d'utiliser la bonne vieille commande DOS comme suggéré précédemment. La syntaxe complète PS prêt à du copier-coller est:
& cmd.exe /c rd /S /Q $folderToDelete
Pour une raison quelconque la réponse de John Rees parfois ne fonctionnait pas dans mon cas. Mais il m'a conduit dans la direction suivante. D'abord, je tente de supprimer le répertoire récursive avec l'option poussette récursif. Plus tard, je descends dans tous les subdir qui reste et supprimer 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
}
}
}
Je pris une autre approche inspirée par @ john-rees ci-dessus - surtout quand son approche a commencé à échouer pour moi à un moment donné. En fait récursif la sous-arborescence et trier les fichiers par leur chemin longueur - supprimer de la plus longue à la plus courte
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 de -LiteralPath, voici une autre gotchya qui peuvent vous frapper: https://superuser.com/q/212808
Vraiment simple:
remove-item -path <type in file or directory name>, press Enter
Une autre astuce utile:
Si vous trouvez un grand nombre de fichiers avec convention de nom identique ou similaire (comme fichier mac avec le nom du préfixe dot ... qui célèbre pulltion de fichier), vous pouvez facilement les enlever avec une seule ligne de la Powershell comme ceci:
ls -r .* | rm
Cette ligne va supprimer tous les fichiers avec un point au début du nom dans le répertoire courant, et tous les fichiers ayant les mêmes circonstances à l'intérieur d'autres dossiers dans ce répertoire aussi. Sachez à ce sujet lors de son utilisation. : D
Suppression d'un arbre de dossier complet fonctionne parfois et échoue parfois avec des erreurs « Répertoire non vide ». Par la suite tenter 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, si une idée peut tirer de ce StackOverflow affichage .
Je suis en mesure de contourner ces problèmes en spécifiant l'ordre dans lequel les éléments contenus dans le dossier sont supprimés, et en ajoutant des retards. 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 Utilisation des propriétés dans Calculée PowerShell utile me à obtenir une liste des sous-dossiers classés par profondeur.
problèmes de fiabilité similaires avec RD / S / Q peut être résolu en exécutant RD / S / Q deux fois - idéalement avec une pause entre les deux (par exemple en utilisant 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
Pour supprimer le contenu complet, y compris la structure dossier utilisation
get-childitem $dest -recurse | foreach ($_) {remove-item $_.fullname -recurse}
Le -recurse
ajouté à remove-item
assure des invites interactives sont désactivées.
del <dir> -Recurse -Force # I prefer this, short & sweet
ou
remove-item <dir> -Recurse -Force
Si vous avez un répertoire énorme alors ce que je fais habituellement est
while (dir | where name -match <dir>) {write-host deleting; sleep -s 3}
Exécuter ce sur un autre terminal et Powershell s'arrête quand il est fait.
$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"
}
A écrit ci-dessus pour nettoyer certains fichiers journaux sans supprimer le répertoire parent et cela fonctionne parfaitement!
rm -r <folder_name>
c:\>rm -r "my photos"