A few years ago I think I posted some PowerShell clean up tools. These were functions designed to help clear out old files, especially for folders like TEMP. Recently I decided to upgrade them to at least PowerShell 3.0 to take advantage of v3 cmdlets and features. I use these periodically to clean out my temp folders. I should probably set them up as a scheduled job to run monthly, but I haven't gotten around to that yet. In the mean time, let me show you what I have.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
First, I have a function to delete files from a directory that were last modified after a given date.
#requires -version 3.0
Function Remove-File {
<#
.SYNOPSIS
Delete files based on file age.
.DESCRIPTION
This function will go start at a specified path and delete files and folders that are older than a
specified date and time. The comparison is made to the file's last modified time. The last access time
doesn't always accurately reflect when a file was last used. Typically you will use this function to
clean out temp folders.
.PARAMETER Path
The folder path to search. The default is the temp folder.
.PARAMETER Cutoff
The date time threshold
.PARAMETER Recurse
Recursively search from the starting path.
.PARAMETER Hidden
Include hidden and system files files.
.EXAMPLE
PS C:\> Remove-File -recurse -cutoff (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime -whatif
Remove all files in the temp folder that are older than the computer's startup time.
.EXAMPLE
PS C:\> "C:\work","$env:temp","$env:windir\temp" | Remove-File -cutoff (Get-Date).AddDays(-30) -recurse -hidden
This command will search the 3 specified paths for all files that haven't been modified in 30 days and delete them.
.NOTES
NAME : Remove-File
VERSION : 3.0
LAST UPDATED: 11/11/2013
AUTHOR : Jeffery Hicks
.LINK
https://jdhitsolutions.com/blog/2013/11/powershell-clean-up-tools
.LINK
Get-ChildItem
Remove-Item
.INPUTS
String
.OUTPUTS
None
#>
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(Position=0)]
[ValidateScript({Test-Path $_})]
[string]$Path=$env:temp,
[Parameter(Position=1,Mandatory,
HelpMessage= "Enter a cutoff date. All files after this date will be removed.")]
[ValidateScript({$_ -lt (Get-Date)})]
[datetime]$Cutoff,
[Switch]$Recurse,
[Switch]$Hidden
)
Write-Host "Removing files in $path older than $cutoff" -foregroundcolor CYAN
#create a hashtable of parameters to splat to Get-ChildItem
$paramHash=@{
Path= $Path
ErrorAction= "Stop"
File= $True
}
#add optional parameters
if ($Recurse) {
$paramHash.Add("Recurse",$True)
}
if ($Hidden) {
$paramHash.Add("Force",$True)
}
Try {
$files = Get-ChildItem @paramhash | where {$_.lastwritetime -lt $cutoff}
}
Catch {
Write-Warning "Failed to enumerate files in $path"
Write-Warning $_.Exception.Message
#Bail out
Return
}
if ($files) {
#only remove files if anything was found
$files| Remove-Item -Force
$stats= $files | Measure-Object -Sum length
$msg="Attempted to delete {0} files for a total of {1} MB ({2} bytes)" -f $stats.count,($stats.sum/1MB -as [int]),$stats.sum
Write-Host $msg -foregroundcolor CYAN
} #if $files
else {
Write-Host "No files found to remove" -ForegroundColor Yellow
}
} #close function
The function supports -WhatIf so that if I run it, Remove-Item will only show me what it would delete. I use a hashtable to build a set of parameters to splat to Get-ChildItem. I love this technique for building dynamic commands. I use this command on my temp folders to delete files older than the last time the computer booted. My assumption is that anything in TEMP older than the last boot time is fair game for deletion.
If you look at this function, you'll notice that it only affects files. It leaves folder alone. I suppose I could modify it to remove old folders as well, but there's a chance the folder might have a newer file somewhere in the hierarchy that shouldn't be deleted so I decided to simply focus on old files. To clean up folders, I use this:
#requires -version 3.0
#remove directories that have no files.
<#
****************************************************************
* DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
* THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF *
* YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
* DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. *
****************************************************************
#>
Function Remove-EmptyFolder {
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter a root directory path")]
[ValidateScript({Test-Path $_})]
[string]$Path=$env:temp
)
Write-Host "Removing empty folders in $Path" -ForegroundColor Cyan
#get top level folders
$Folders = Get-ChildItem -Path $path -Directory -Force
#test each folder for any files
foreach ($folder in $folders) {
If (-NOT ($folder | dir -file -Recurse)) {
Write-Host "Removing $($folder.FullName)" -ForegroundColor Red
$folder | Remove-Item -Force -Recurse
}
} #end foreach
} #end Remove-EmptyFolder
This command looks for empty folders, or more precisely folders with no files. The function gets all of the top-level folders in the specified path and then searches each folder recursively for any files. If no files are found, the folder is removed.
The two tools are great on their own. To put them to use, I created a small script.
#requires -version 3.0 <# CleanTemp.ps1 **************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB SETTING. USE AT YOUR OWN RISK. * * **************************************************************** #> #dot source functions . C:\scripts\Remove-EmptyFolder.ps1 . C:\scripts\Remove-File3.ps1 #get last boot up time. #Get-CIMInstance will return LastBootUpTime as a datetime object. No converting required. $bootTime = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime #delete files in temp folders older than the last bootup time Remove-File $env:temp $boottime -recurse -hidden Remove-File D:\Temp $boottime -recurse -hidden Write-Host "Removing empty folders" -ForegroundColor Cyan Remove-EmptyFolder $env:temp Remove-EmptyFolder D:\temp
I think of the script as a "canned" PowerShell session. Instead of my typing the commands to clean up a few folders, I simply run the script. I inserted some Write-Host commands so I could know what the script was doing. I clean out all the old files first and then make a second pass to delete any empty folders. I trust it goes without saying that if you want to use these, you have to test in a non-production environment.
Enjoy.

2 thoughts on “PowerShell Clean Up Tools”
Comments are closed.