PowerShell Script to delete files/folders order than X days

If your like me you have a lot of backups, downloads, and/or copies files in various folders and cleaning it up and can be time consuming. To help with that I put together this small powershell script/function that will help clean it up (or at least handle the removing of items based on being way to old!)

To use the script, copy/paste it into your favorite editor, save it as “Remove-AgedFiles.ps1” to an easy to remember location (Desktop, your scripts folder, etc) and you are ready to go.

Usage would look like this:

[PS] .\Remove-ItemsItems.ps1 -Path e:\Downloads -NumberOfDaysOld 10

Note: script support the -WhatIf and -Debug standard parameters so that you can run it without actually changing anything on the system so you can run it like this to see what files will be deleted without actually having them removed from you system (great for validating what is going to be done as a sanity check)

[PS] .\Remove-ItemsItems.ps1 -Path e:\Downloads -NumberOfDaysOld 10 -WhatIf -Debug 

And without further adieu here is the actual script

[CmdletBinding(SupportsShouldProcess)]
param (
    [Parameter(Mandatory)]
    [IO.DirectoryInfo] $Path,
    [int] $NumberOfDaysOld = 30,
    [Switch] $IgnoreEmptFolders, 
    [DateTime] $now = [DateTime]::MinValue,
    [String] $LogFile = "$((Get-Location).Drive.Name)\AgedFiles-$($env:computername)-$((Get-Date).ToString("yyyyMMdd")).log"
)

function Write-Log {
    param([string]$message)

    $msg = (((Get-Date).ToString()) + " - " + $Message) 

    Write-Host $msg

    Add-Content $LogFile -value $msg
}

if (Test-Path $LogFile) {
    Write-Host "Removing previous log file" -ForegroundColor Yellow
    Remove-Item $LogFile 
}

# Do we have a valid dates? If note lets get the current date
if ($now -eq [DateTime]::MinValue) {
    $now = (Get-Date)
}

$retentionPeriod = [TimeSpan]::FromDays($NumberOfDaysOld)

Write-Log "Starting process of removing aged files"

# Lets find all of the files that haven't been "changed" in the last X days
Write-Log "Retrieving list of files older than '$($retentionPeriod.Days)' days to remove"
$oldFiles = Get-ChildItem $Path.FullName -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $now.Subtract($retentionPeriod) }

# Lets get a lost of all of the folders we need to process and then filter them down to only the empty ones that can be removed
if (-Not ($IgnoreEmptFolders.IsPresent)) {
    Write-Log "Retrieving list of folders to remove"
    $folders = Get-ChildItem $Path.FullName -Recurse -Directory -ErrorAction SilentlyContinue

    $emptyFolders = $folders `
        | Where-Object { (Get-ChildItem $_.FullName -file -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -gt $now.Subtract($retentionPeriod) }) -eq $null } `
        | Sort-Object -Property @{ Expression={ $_.FullName.Split([IO.Path]::DirectorySeparatorChar).Count }; Descending=$true }  
}

# Lets delete all of the old files
Write-Log "Removing Files older than '$($retentionPeriod.Days)' days"
Write-Debug "Files to remove: `n`t$(($oldFiles | Select -ExpandProperty FullName) -join "`r`n`t")"
if ($PSCmdlet.ShouldProcess($Path.FullName, "Remove files older than '$($retentionPeriod.Days)' days")) {
    $oldFiles | Remove-Item -Force -Verbose | Out-File $LogFile -Append
} else {
    $oldFiles | Out-File $LogFile -Append
}

if (-Not ($IgnoreEmptFolders.IsPresent)) {
    # Lets delete all of the empty folders
    Write-Log "Cleaning up empty folders"
    Write-Debug "Folders to remove: `n`t$(($oldFiles | Select -ExpandProperty FullName) -join "`r`n`t")"
    if ($PSCmdlet.ShouldProcess($Path.FullName, "Remove empty folders")) {
        $emptyFolders | Remove-Item -Force -Recurse -Verbose | Out-File $LogFile -Append
    } else {
        $emptyFolder | Out-File $LogFile -Append
    }
}

Write-Log "Completed process of removing aged files"