Skip to main content

Clean up Files and Folders using PowerShell

· 3 min read
Naw Awn

Spring cleaning is on its way!

Sometimes you hear from IT Support saying "the server is very slow, the required service has stopped running and the Windows updates installation failed, etc." When you logon to the server and check what went wrong, you realise the server is running out of space on C: drive and you need to delete some old files or expand the disk to fix the issue. This could become a recurring task for certain VMs. The quick and easy solution is to write a script and run it as a regular maintenance task.

The below is a very simple and basic script to do the job.

$Day        = -7
$FolderPath = "D:\Backups"
Get-ChildItem -Path $FolderPath | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays($Day)} | Remove-Item -Force

If you want to make your script more manageable, you could turn the script into a function, split the variables into a configuration file and put some basic logging mechanism.

Cleanup-Script.ps1
[CmdletBinding()]
Param()

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$Config = Import-PowershellDataFile -Path "$here\Cleanup-Config.psd1"

Function Remove-OldFiles{
Param(
[Parameter()]
[Int]$Day,
[String]$FolderPath
)
Process{
If ($Day -gt 0){
Write-Warning "The Day value should be in negative."
Return
}
$FileList = (Get-ChildItem -Path $FolderPath).Where{$_.LastWriteTime -lt (Get-Date).AddDays($Day)}
If ($FileList){
(Get-Date).ToString() | Add-Content -Path "$FolderPath\DeletionLog.txt"
$FileList | Add-Content -Path "$FolderPath\DeletionLog.txt"
$FileList | Remove-Item -Force -ErrorVariable errLog
If ($errLog){
$errLog | Add-Content -Path "$FolderPath\DeletionLog.txt"
}
}
}
}
Remove-OldFiles -Day $Config.Day -FolderPath $Config.FolderPath
Cleanup-Config.psd1
@{
Day = -7
FolderPath = 'D:\Backups'
}

As you probably notice, the script doesn't use the recurse parameter on Get-ChildItem cmdlet. If you do, that could also delete the folder structure you need to maintain. At this point, you would think you could just add the File switch like this:

Get-ChildItem -Path $FolderPath -Recurse -File

This will definitely work if your scenario fits the requirement. The way I manage when you need more control over what is getting deleted is by using the configuration file and add a loop to go through each item in it.

Cleanup-Config.psd1
@{
'Backup-Example'@{
Day = -5
FolderPath = 'D:\Backups\Example'
}
'Backup-SQL01'@{
Day = -5
FolderPath = 'D:\Backups\SQL01'
}
}

Add the foreach loop at the end of the script file replacing this line:

Remove-OldFiles -Day $Config.Day -FolderPath $Config.FolderPath

Cleanup-Script.ps1
Foreach ($item in $Config.Keys){
$Param = @{
Day = $Config[$item].Day
FolderPath = $Config[$item].FolderPath
}
Write-Verbose "Removing old files from $($Config[$item].FolderPath)"
Remove-OldFiles @Param
}

Thinking about updating the script to adjust to your need, the sky's the limit. Hopefully the above script helps if you are automating the deletion of old files in your environment.