subcarpetas para eliminar carpetas borrar bat archivos file powershell recursion delete-directory

file - para - ¿Cómo eliminar subcarpetas vacías con PowerShell?



borrar carpetas powershell (7)

Tengo un recurso que es un "cajón de basura" para los usuarios finales. Pueden crear carpetas y subcarpetas como mejor les parezca. Necesito implementar un script para eliminar archivos creados con más de 31 días de antigüedad.

Eso comenzó con Powershell. Necesito seguir el script de eliminación de archivos eliminando las subcarpetas que ahora están vacías. Debido a la anidación de subcarpetas, debo evitar eliminar una subcarpeta que está vacía de archivos, pero tiene una subcarpeta debajo que contiene un archivo.

Por ejemplo:

  • FILE3a tiene 10 días. FILE3 tiene 45 días.
  • Quiero limpiar la estructura eliminando archivos de más de 30 días y eliminar las subcarpetas vacías.

C:/Junk/subfolder1a/subfolder2a/FILE3a C:/Junk/subfolder1a/subfolder2a/subfolder3a C:/Junk/subfolder1a/subfolder2B/FILE3b

Resultado deseado:

  • Eliminar: FILE3b , subfolder2B y subfolder3a .
  • Deje: subfolder1a , subfolder2a y FILE3a .

Puedo limpiar recursivamente los archivos. ¿Cómo limpio las subcarpetas sin borrar la subfolder1a ? (La carpeta "Basura" siempre permanecerá).


Agregando a la última:

while (Get-ChildItem $StartingPoint -recurse | where {!@(Get-ChildItem -force $_.fullname)} | Test-Path) { Get-ChildItem $StartingPoint -recurse | where {!@(Get-ChildItem -force $_.fullname)} | Remove-Item }

Esto lo completará donde continuará la búsqueda para eliminar cualquier carpeta vacía bajo $ StartingPoint


En el espíritu de la primera respuesta, esta es la forma más corta de eliminar los directorios vacíos:

ls -recurse | where {!@(ls -force $_.fullname)} | rm -whatif

El indicador -force es necesario para los casos en que los directorios tienen carpetas ocultas, como .svn


Esto funcionó para mí.

$limit = (Get-Date).AddDays(-15) $path = "C:/Some/Path"

Eliminar archivos anteriores al $limit :

Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

Elimine cualquier directorio vacío que quede después de eliminar los archivos antiguos:

Get-ChildItem -Path $path -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse


Esto ordenará los subdirectorios antes de los directorios principales que trabajan alrededor del problema del directorio anidado vacío.

dir -Directory -Recurse | %{ $_.FullName} | sort -Descending | where { !@(ls -force $_) } | rm -WhatIf


Haría esto en dos pasos: eliminar primero los archivos antiguos y luego los vacíos:

Get-ChildItem -recurse | Where {!$_.PSIsContainer -and ` $_.LastWriteTime -lt (get-date).AddDays(-31)} | Remove-Item -whatif Get-ChildItem -recurse | Where {$_.PSIsContainer -and ` @(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} | Remove-Item -recurse -whatif

Este tipo de operación demuestra el poder de las canalizaciones anidadas en PowerShell que muestra el segundo conjunto de comandos. Utiliza una canalización anidada para determinar recursivamente si algún directorio tiene cero archivos debajo de él.


Necesitaba algunas características amigables para la empresa. Aquí está mi opinión.

Comencé con el código de otras respuestas, luego agregué un archivo JSON con la lista de carpetas originales (incluido el conteo de archivos por carpeta). Se eliminaron los directorios vacíos y se registraron.

https://gist.github.com/yzorg/e92c5eb60e97b1d6381b

param ( [switch]$Clear ) # if you want to reload a previous file list #$stat = ConvertFrom-Json (gc dir-cleanup-filecount-by-directory.json -join "`n") if ($Clear) { $stat = @() } elseif ($stat.Count -ne 0 -and (-not "$($stat[0].DirPath)".StartsWith($PWD.ProviderPath))) { Write-Warning "Path changed, clearing cached file list." Read-Host -Prompt ''Press -Enter-'' $stat = @() } $lineCount = 0 if ($stat.Count -eq 0) { $stat = gci -Recurse -Directory | %{ # -Exclude ''Visual Studio 2013'' # test in ''Documents'' folder if (++$lineCount % 100 -eq 0) { Write-Warning "file count $lineCount" } New-Object psobject -Property @{ DirPath=$_.FullName; DirPathLength=$_.FullName.Length; FileCount=($_ | gci -Force -File).Count; DirCount=($_ | gci -Force -Directory).Count } } $stat | ConvertTo-Json | Out-File dir-cleanup-filecount-by-directory.json -Verbose } $delelteListTxt = ''dir-cleanup-emptydirs-{0}-{1}.txt'' -f ((date -f s) -replace ''[-:]'','''' -replace ''T'',''_''),$env:USERNAME $stat | ? FileCount -eq 0 | sort -property @{Expression="DirPathLength";Descending=$true}, @{Expression="DirPath";Descending=$false} | select -ExpandProperty DirPath | #-First 10 | ?{ @(gci $_ -Force).Count -eq 0 } | %{ Remove-Item $_ -Verbose # -WhatIf # uncomment to see the first pass of folders to be cleaned** $_ | Out-File -Append -Encoding utf8 $delelteListTxt sleep 0.1 } # ** - The list you''ll see from -WhatIf isn''t a complete list because parent folders # might also qualify after the first level is cleaned. The -WhatIf list will # show correct breath, which is what I want to see before running the command.


Para eliminar archivos de más de 30 días:

get-childitem -recurse | ? {$_.GetType() -match "FileInfo"} | ?{ $_.LastWriteTime -lt [datetime]::now.adddays(-30) } | rm -whatif

(Simplemente elimine el -whatif para realizar).

Ir a la par de:

get-childitem -recurse | ? {$_.GetType() -match "DirectoryInfo"} | ?{ $_.GetFiles().Count -eq 0 -and $_.GetDirectories().Count -eq 0 } | rm -whatif