Pregunta

Tengo un porcentaje que es un "cajón de basura" para los usuarios finales. Son capaces de crear carpetas y subcarpetas como mejor les parezca. Necesito implementar una secuencia de comandos para borrar archivos creados más de 31 días de edad.

Tengo que empezó con Powershell. Necesito hacer un seguimiento de la eliminación de la escritura de archivos mediante la supresión de las subcarpetas que ahora están vacías. Debido a la anidación de las subcarpetas, necesitaré para evitar la eliminación de una subcarpeta que está vacía de archivos, pero tiene una subcarpeta debajo de ella que contiene un archivo.

Por ejemplo:

  • FILE3a es de 10 días de edad. FILE3 es de 45 días de edad.
  • Quiero limpiar la estructura de la eliminación de archivos de más de 30 días, y eliminar 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.
  • Dejar:. subfolder1a, subfolder2a y FILE3a

Me puede limpiar de forma recursiva seguridad de los archivos. ¿Cómo se limpia hasta las subcarpetas sin eliminar subfolder1a? (La carpeta "chatarra" siempre permanecerá.)

¿Fue útil?

Solución

Me gustaría hacer esto en dos pasadas - eliminar los archivos antiguos primero y luego los directorios 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 demos el poder de tuberías anidadas en PowerShell que demuestra el segundo conjunto de comandos. Se utiliza una tubería de forma recursiva anidada para determinar si algún directorio tiene archivos de cero debajo de ella.

Otros consejos

En el espíritu de la primera respuesta, aquí es el camino más corto para eliminar los directorios vacíos:

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

Se necesita la bandera de force para los casos en que los directorios han ocultado carpetas, como .svn

Esto ordenará subdirectorios antes directorios padres que trabajan en torno al problema de directorios anidados vacía.

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

Adición 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 hará que sea completo en el que va a continuar la búsqueda para eliminar las carpetas vacías bajo el StartingPoint $

Yo necesitaba algunas características de la empresa de usar. Aquí está mi tomar.

Me comenzó con código de otras respuestas, a continuación, añade un archivo JSON con la lista de carpetas original (incluyendo el número de archivos por carpeta). Eliminado los directorios vacíos y registrar aquellos.

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

(Basta con retirar la -whatif que realiza realmente.)

Seguimiento con:

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

Esto funcionó para mí.

$limit = (Get-Date).AddDays(-15) 

$path = "C:\Some\Path"

Eliminar archivos mayores de la $limit:

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

Eliminar todos los directorios vacíos que quedan después de la eliminación de los viejos archivos:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top