it-swarm-es.com

¿Cómo eliminar recursivamente un directorio completo con PowerShell 2.0?

¿Cuál es la forma más sencilla de eliminar por la fuerza un directorio y todos sus subdirectorios en PowerShell? Estoy usando PowerShell V2 en Windows 7.

He aprendido de varias fuentes que el comando más obvio, Remove-Item $targetDir -Recurse -Force, no funciona correctamente. Esto incluye una declaración en la ayuda en línea de PowerShell V2 (que se encuentra usando Get-Help Remove-Item -Examples) que dice:

... Debido a que el parámetro Recurse en este cmdlet es defectuoso, el comando usa el cmdlet Get-Childitem para obtener los archivos deseados, y usa el operador de canalización para pasarlos al cmdlet Remove-Item ...

He visto varios ejemplos que usan Get-ChildItem y lo canalizan a Remove-Item , pero los ejemplos generalmente eliminan algunos conjuntos de archivos basados ​​en un filtro, no en todo el directorio.

Estoy buscando la forma más limpia de eliminar un directorio completo, archivos y directorios secundarios, sin generar ningún mensaje de advertencia para el usuario utilizando la menor cantidad de código. Una sola línea sería agradable si es fácil de entender.

239
Matt Spradley
Remove-Item -Recurse -Force some_dir

de hecho funciona como se anuncia aquí.

rm -r -fo some_dir

son alias de taquigrafía que funcionan también.

Hasta donde lo entendí, el parámetro -Recurse simplemente no funciona correctamente cuando intenta eliminar un conjunto de archivos filtrados de forma recursiva. Para matar un solo directorio y todo lo que está debajo parece funcionar bien.

409
Joey

Solía:

rm -r folderToDelete

Esto me funciona como un encanto (lo robé de Ubuntu).

36
Tuan Jinn

Cuando borro archivos recursivamente usando un simple Remove-Item "folder" -Recurse A veces veo un error intermitente: [folder] cannot be removed because it is not empty.

Esta respuesta intenta evitar ese error al eliminar individualmente los archivos.

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 detalle importante es la clasificación de todos los elementos con pspath -Descending para que las hojas se eliminen antes que las raíces. La clasificación se realiza en el parámetro pspath, ya que tiene más posibilidades de trabajar para proveedores distintos del sistema de archivos. El parámetro -Include es solo una conveniencia si desea filtrar los elementos que desea eliminar.

Se divide en dos funciones ya que me parece útil ver lo que voy a eliminar ejecutando

Get-Tree some_dir | select fullname
19
John Rees

Prueba este ejemplo. Si el directorio no existe, no se genera ningún error. Es posible que necesite PowerShell v3.0.

remove-item -path "c:\Test Temp\Test Folder" -Force -Recurse -ErrorAction SilentlyContinue
10
steve
rm -r ./folder -Force    

...trabajó para mi

9
stevethecollier

Use el comando DOS de la vieja escuela:

rd /s <dir>
8
Anonymous

Para evitar los errores "El directorio no está vacío" de la respuesta aceptada, simplemente use el comando antiguo de DOS como se sugirió anteriormente. La sintaxis completa de PS lista para copiar y pegar es:

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

Por alguna razón, la respuesta de John Rees a veces no funcionaba en mi caso. Pero me llevó en la siguiente dirección. Primero trato de eliminar el directorio de forma recursiva con la opción buggy -recurse. Luego desciendo a cada subdirigido que queda y borro todos los archivos.

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

Tomé otro enfoque inspirado en @ john-rees arriba, especialmente cuando su enfoque comenzó a fallar para mí en algún momento. Básicamente recuenta el subárbol y ordena los archivos por su longitud de ruta: borra de la más larga a la más corta

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

Con respecto a la magia -LiteralPath, aquí hay otro gotchya que puede estar afectándote: https://superuser.com/q/212808

2
Peter McEvoy

La eliminación de un árbol de carpetas completo a veces funciona y otras veces falla con errores de "Directorio no vacío". Posteriormente, intentar verificar si la carpeta aún existe puede dar lugar a errores de "Acceso denegado" o "Acceso no autorizado". No sé por qué sucede esto, aunque se puede obtener alguna información de esta publicación de StackOverflow .

He podido solucionar estos problemas especificando el orden en que se eliminan los elementos dentro de la carpeta y agregando demoras. Lo siguiente funciona bien para mí:

# 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 artículo de Microsoft TechNet Uso de propiedades calculadas en PowerShell me ayudó a obtener una lista de subcarpetas clasificadas por profundidad.

Problemas de confiabilidad similares con RD/S/Q se pueden resolver ejecutando RD/S/Q dos veces - idealmente con una pausa entre ellos (es decir, utilizando ping as) mostrado a continuación).

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

Realmente simple:

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

Para eliminar el contenido completo incluyendo la estructura de carpetas use

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

El -recurse agregado a remove-item asegura que las solicitudes interactivas estén deshabilitadas.

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

OR

remove-item <dir> -Recurse -Force

Si tienes un directorio enorme, entonces lo que normalmente hago es

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

Ejecuta esto en otra terminal powershell y se detendrá cuando haya terminado.

1
Gajendra D Ambi

Otro truco útil:

Si encuentra una gran cantidad de archivos con la misma convención de nombre o similar (como el archivo mac con el nombre de prefijo de punto ... ese famoso archivo), puede eliminarlos fácilmente con una sola línea del powershell como esta:

ls -r .* | rm

Esta línea eliminará todos los archivos con un punto al principio del nombre dentro del directorio actual, y todos los archivos con las mismas circunstancias dentro de otras carpetas dentro de este directorio también. Sé consciente de ello cuando lo uses. :RE