Delete Files Older Than X Days With Specific Extensions Using PowerShell

Recently, I was working on a server cleanup project where I needed to delete thousands of log files that were older than 90 days. These files were taking up valuable disk space, and manually identifying and deleting them would have been incredibly time-consuming.

In this tutorial, I’ll show you how to create PowerShell scripts that can identify and delete files older than a specified number of days with particular extensions.

Let’s explore different approaches to delete files older than X days with specific extensions in PowerShell.

Method 1: Basic PowerShell Script to Delete Old Files

The simplest approach uses PowerShell’s Get-ChildItem cmdlet combined with Where-Object to filter files by date and extension, then Remove-Item to delete them.

Here’s a basic script that will delete log files older than 30 days:

# Set parameters
$Path = "C:\Logs"
$DaysBack = 30
$Extension = "*.log"

# Calculate the date threshold
$CurrentDate = Get-Date
$DateThreshold = $CurrentDate.AddDays(-$DaysBack)

# Get files older than the threshold and delete them
Get-ChildItem -Path $Path -Filter $Extension -Recurse |
    Where-Object { $_.LastWriteTime -lt $DateThreshold } |
    Remove-Item -Force

Let me break down how this script works:

  1. We define three parameters: the folder path, how many days back to check, and the file extension.
  2. We calculate the date threshold by taking the current date and subtracting the specified number of days.
  3. We use Get-ChildItem to find all files with the specified extension.
  4. The Where-Object cmdlet filters the list to include only files older than our threshold date.
  5. Finally, Remove-Item deletes the filtered files.

When I used this script on my development server, it successfully cleared over 2GB of old log files in seconds!

Check out How to Count Files in a Folder Using PowerShell

Method 2: Create a Reusable Function

Let me make it easy for you. I will show you how to create a reusable function using PowerShell. You can call this function with different parameters.

Here is the complete PowerShell script:

function Remove-OldFiles {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [string]$FolderPath,

        [Parameter(Mandatory=$true)]
        [int]$DaysOld,

        [Parameter(Mandatory=$true)]
        [string]$Extension,

        [switch]$WhatIf
    )

    $CurrentDate = Get-Date
    $DateThreshold = $CurrentDate.AddDays(-$DaysOld)

    Write-Host "Searching for *$Extension files older than $DaysOld days in $FolderPath..."

    $FilesToDelete = Get-ChildItem -Path $FolderPath -Filter "*$Extension" -Recurse |
        Where-Object { $_.LastWriteTime -lt $DateThreshold }

    $TotalSize = ($FilesToDelete | Measure-Object -Property Length -Sum).Sum / 1MB
    Write-Host "Found $($FilesToDelete.Count) files to delete (approximately $([math]::Round($TotalSize, 2)) MB)"

    if ($WhatIf) {
        $FilesToDelete | ForEach-Object {
            Write-Host "Would delete: $($_.FullName) - Last modified: $($_.LastWriteTime)"
        }
    }
    else {
        $FilesToDelete | Remove-Item -Force
        Write-Host "Deleted $($FilesToDelete.Count) files"
    }
}

This function adds several improvements:

  1. Parameter validation to ensure you provide all required information
  2. A -WhatIf parameter that lets you preview what would be deleted without actually deleting anything
  3. Detailed reporting that shows how many files will be deleted and their total size
  4. Better error handling through the [CmdletBinding()] attribute

You can call this function in different ways:

# Delete log files older than 60 days
Remove-OldFiles -FolderPath "D:\ServerBackups" -DaysOld 60 -Extension ".log"

# Preview deletion of old CSV files without actually deleting them
Remove-OldFiles -FolderPath "C:\Reports" -DaysOld 90 -Extension ".csv" -WhatIf

Check out PowerShell Write to File UTF-8

Method 3: Handle Multiple Extensions at Once

Sometimes you need to delete files with different extensions. Here’s how to handle multiple extensions in a single PowerShell script:

# Set parameters
$Path = "C:\UserData\TempFiles"
$DaysBack = 45
$Extensions = @(".tmp", ".log", ".bak")

# Calculate the date threshold
$CurrentDate = Get-Date
$DateThreshold = $CurrentDate.AddDays(-$DaysBack)

# Process each extension
foreach ($Extension in $Extensions) {
    Write-Host "Processing files with extension: $Extension"

    $FilesToDelete = Get-ChildItem -Path $Path -Filter "*$Extension" -Recurse |
        Where-Object { $_.LastWriteTime -lt $DateThreshold }

    $Count = $FilesToDelete.Count

    if ($Count -gt 0) {
        $FilesToDelete | Remove-Item -Force
        Write-Host "Deleted $Count files with extension $Extension" -ForegroundColor Green
    }
    else {
        Write-Host "No files found with extension $Extension to delete" -ForegroundColor Yellow
    }
}

I’ve used this approach to clean up our company’s image processing server, where we needed to remove temporary files with various extensions (.tmp, .bak, .old) that accumulated during processing.

Check out PowerShell Test-Path

Method 4: Schedule with Task Scheduler

You can schedule your PowerShell script to run periodically using Windows Task Scheduler for automated maintenance.

First, save your script as a .ps1 file, for example, CleanupOldFiles.ps1.

Then, create a scheduled task:

  1. Open Task Scheduler (taskschd.msc)
  2. Create a new Basic Task
  3. Set a name like “Weekly File Cleanup”
  4. Choose your trigger (e.g., Weekly on Sunday at 2:00 AM)
  5. For the action, select “Start a program”
  6. In the Program/script field, enter: powershell.exe
  7. In the Add arguments field, enter: -ExecutionPolicy Bypass -File "C:\Scripts\CleanupOldFiles.ps1"

This ensures your cleanup runs automatically at the scheduled time, keeping your system tidy without manual intervention.

Check out Write to File Line by Line in PowerShell

Method 5: Logging Deletion Activity

For audit purposes, I recommend adding logging capabilities to your script:

# Set parameters
$Path = "C:\ApplicationLogs"
$DaysBack = 30
$Extension = "*.txt"
$LogFile = "C:\Scripts\Logs\DeletionLog.txt"

# Ensure log directory exists
$LogDir = Split-Path $LogFile -Parent
if (!(Test-Path $LogDir)) {
    New-Item -ItemType Directory -Path $LogDir -Force
}

# Start logging
$TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"[$TimeStamp] Starting cleanup process for *$Extension files older than $DaysBack days" | Out-File $LogFile -Append

# Calculate the date threshold
$CurrentDate = Get-Date
$DateThreshold = $CurrentDate.AddDays(-$DaysBack)

# Get files and delete them, logging each one
$Files = Get-ChildItem -Path $Path -Filter $Extension -Recurse |
    Where-Object { $_.LastWriteTime -lt $DateThreshold }

foreach ($File in $Files) {
    try {
        Remove-Item $File.FullName -Force
        "[$TimeStamp] Deleted: $($File.FullName) (Last modified: $($File.LastWriteTime))" | Out-File $LogFile -Append
    }
    catch {
        "[$TimeStamp] ERROR deleting $($File.FullName): $($_.Exception.Message)" | Out-File $LogFile -Append
    }
}

# Log summary
"[$TimeStamp] Cleanup complete. Deleted $($Files.Count) files." | Out-File $LogFile -Append

This script creates a detailed log of all deleted files, including timestamps and any errors that might occur. These logs have saved me countless hours when investigating why certain files were removed or when troubleshooting script issues.

Read Write to File without Carriage Return in PowerShell

Method 6: Delete Specific Files Based on CreationTime

Sometimes, LastWriteTime isn’t the right property to use. For instance, when cleaning up backup files, you might want to use CreationTime instead:

# Set parameters
$Path = "E:\DatabaseBackups"
$DaysBack = 180  # Keep backups for 6 months
$Extension = "*.bak"

# Calculate the date threshold
$CurrentDate = Get-Date
$DateThreshold = $CurrentDate.AddDays(-$DaysBack)

# Get files older than the threshold based on creation time and delete them
Get-ChildItem -Path $Path -Filter $Extension -Recurse |
    Where-Object { $_.CreationTime -lt $DateThreshold } |
    Remove-Item -Force

This approach ensures that you delete files based on their creation date rather than their last modification date.

Best Practices and Considerations

Now, let me show you a few best practices for deleting files older than X Days with Specific Extensions using PowerShell.

  1. Always test with -WhatIf first: Before running a deletion script on production data, use the -WhatIf parameter to preview what will be deleted.
  2. Start with a narrow scope: Begin with a specific folder and extension rather than targeting your entire system.
  3. Consider file importance: Some files, despite their age, might be critical. Add exclusion logic for important files.
  4. Mind the recursion: Be careful when using -Recurse in folders with many subfolders, as the script might take longer to run.
  5. Add error handling: Proper try/catch blocks ensure your script continues running even if it encounters permission issues or locked files.

Check out Append Text to Files in PowerShell

PowerShell Script to Delete Files Older Than 30 Days

Here is a particular example, here, I will explain how to delete files older than 30 days using PowerShell. I’ll show you how to create a PowerShell script that can identify and delete files older than 30 days.

The best approach uses PowerShell’s Get-ChildItem cmdlet combined with Where-Object to filter files by date, then Remove-Item to delete them.

Here’s a basic PowerShell script that will delete files older than 30 days:

# Set parameters
$Path = "C:\Logs"
$DaysBack = 30

# Calculate the date threshold
$CurrentDate = Get-Date
$DateThreshold = $CurrentDate.AddDays(-$DaysBack)

# Get files older than the threshold and delete them
Get-ChildItem -Path $Path -Recurse -File |
    Where-Object { $_.LastWriteTime -lt $DateThreshold } |
    Remove-Item -Force

Let me break down how this script works:

  1. We define two parameters: the folder path and how many days back to check (30 days in this case).
  2. We calculate the date threshold by taking the current date and subtracting 30 days.
  3. We use Get-ChildItem to find all files in the specified path, including subfolders.
  4. The Where-Object cmdlet filters the list to include only files older than our threshold date.
  5. Finally, Remove-Item deletes the filtered files.

When I used this script on my development server, it successfully cleared over 2GB of old files in seconds!

Before you run the script to actually delete files, it’s always a good practice to first see what files would be deleted. You can do this by simply listing the files instead of deleting them:

# Set parameters
$Path = "C:\Logs"
$DaysBack = 30

# Calculate the date threshold
$CurrentDate = Get-Date
$DateThreshold = $CurrentDate.AddDays(-$DaysBack)

# List files older than the threshold
Get-ChildItem -Path $Path -Recurse -File |
    Where-Object { $_.LastWriteTime -lt $DateThreshold } |
    Select-Object FullName, LastWriteTime

This will display a list of the files that would be deleted, along with their last write times, without actually deleting anything.

Conclusion

I hope now you learn how to delete files older than X days with specific extensions using PowerShell. I hope you found this tutorial helpful! If you have any questions or suggestions, feel free to leave them in the comments below.

You may also like the following tutorials:

Power Apps functions free pdf

30 Power Apps Functions

This free guide walks you through the 30 most-used Power Apps functions with real business examples, exact syntax, and results you can see.

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App