Domanda

Ho una quota che è un "cassetto spazzatura" per gli utenti finali. Essi sono in grado di creare cartelle e sottocartelle come meglio credono. Ho bisogno di implementare uno script per eliminare i file creati più di 31 giorni.

Ho iniziato con PowerShell. Ho bisogno di seguire la cancellazione di script file eliminando le sottocartelle che sono ormai vuoti. A causa della nidificazione di sottocartelle, ho bisogno di evitare di eliminare una sottocartella che è vuota di file, ma ha una sottocartella di sotto di essa che contiene un file.

Ad esempio:

  • FILE3a è di 10 giorni. FILE3 è di 45 giorni.
  • Voglio ripulire la struttura di rimozione di file più vecchi di 30 giorni, ed eliminare le sottocartelle vuote.
C:\Junk\subfolder1a\subfolder2a\FILE3a

C:\Junk\subfolder1a\subfolder2a\subfolder3a

C:\Junk\subfolder1a\subfolder2B\FILE3b

risultato desiderato:

  • Elimina: FILE3b, subfolder2B & subfolder3a.
  • Abbandona:. subfolder1a, subfolder2a, e FILE3a

posso ricorsivamente ripulire i file. Come posso pulire le sottocartelle senza eliminare subfolder1a? (La cartella "Junk" rimarrà sempre.)

È stato utile?

Soluzione

Vorrei farlo in due passaggi - eliminando i vecchi file prima e poi le dirs vuoti:

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

Questo tipo di operazione DEMOS potere di condotte nidificati PowerShell cui il secondo insieme di comandi dimostra. Esso utilizza una pipeline nidificato per determinare in modo ricorsivo se qualsiasi directory ha i file di zero sotto di essa.

Altri suggerimenti

Nello spirito della prima risposta, qui è la via più breve per eliminare le directory vuote:

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

è necessaria Il flag force per i casi in cui le directory hanno nascosto le cartelle, come .svn

Ciò ordinerà sottodirectory prima directory genitore che lavora intorno al problema directory annidata vuota.

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

L'aggiunta al ultimo:

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

In questo modo sarà completo dove si continuerà a cercare di rimuovere tutte le cartelle vuote sotto il $ startingPoint

ho bisogno di alcune funzionalità enterprise-friendly. Qui è il mio prendere.

Ho iniziato con il codice da altre risposte, poi aggiunse un file JSON con elenco delle cartelle originali (tra cui il numero di file per cartella). Rimosso le directory vuote e registrare quelli.

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.

Per rimuovere i file più vecchi di 30 giorni:

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

(È sufficiente rimuovere il -whatif per eseguire effettivamente.)

Follow-up con:

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

Questo ha funzionato per me.

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

$path = "C:\Some\Path"

Elimina file più vecchi rispetto alla $limit:

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

Elimina le directory vuoti lasciati alle spalle dopo l'eliminazione dei vecchi file:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top