specific script remove force files delete all windows powershell windows-7 filesystems delete-directory

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



powershell list files in directory (15)

Al eliminar archivos de forma recursiva con una 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 a eliminar.

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

Get-Tree some_dir | select fullname

¿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 utilizando 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 utilizan 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.


La eliminación de un árbol de carpetas completo a veces funciona y a 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 .

He podido solucionar estos problemas especificando el orden en que se eliminan los elementos dentro de la carpeta y agregando retrasos. 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 sobre el 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 como se muestra 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


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 garantiza que las -recurse interactivas estén deshabilitadas.


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


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 } } }


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


Realmente simple:

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


Solía:

rm -r folderToDelete

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


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


Use el comando DOS de la vieja escuela:

rd /s <dir>


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 ... el 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. Tenga cuidado al usarlo. :RE


$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" }

¡Escribí lo anterior para limpiar algunos archivos de registro sin eliminar el directorio principal y esto funciona perfectamente!


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 intentas eliminar un conjunto filtrado de archivos de forma recursiva. Para matar un solo directorio y todo lo que está debajo parece funcionar bien.


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

O

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.


rm -r ./folder -Force

...trabajó para mi