rabin.blog

Auto-Organize Downloads Folder Powershell Script | Windows/macOS/Linux

4 min read

Your Downloads folder is a graveyard. PDFs from 2023, installer files for software you already installed, and random screenshots you took once and never looked at again.

And every time you open it, you think: “I should clean this up.” 

Then you don’t.

I built this script because I was tired (and also lazy) of that cycle. It’s not fancy stuff. It just works.

The Problem Nobody Talks About

Most “cleanup” solutions are too aggressive. They delete stuff you needed. Or they’re too manual, which means you won’t do it. The sweet spot is:

  1. Auto-sort downloads by type so you can find things
  2. Stage old files for deletion, don’t nuke them immediately
  3. Give you a grace period to recover anything you actually need

That’s exactly what this script does.

How It Works (The 90-Day Rule)

Day 0:   Download lands in root → Auto-sorted to category folder
Day 60:  Still untouched in Documents/Images → Moved to Trash-Temp
Day 90:  Still in Trash-Temp → Permanently deleted

Total lifecycle: 90 days. That’s enough time to realize you need something, but not so long that you’re hoarding garbage forever.

The Folder Structure

Downloads/
├── 01-Software/          # .exe, .msi, .dmg, .pkg
├── 02-WordPress/         # Plugin/theme ZIPs (pattern-matched)
├── 03-Documents/         # PDFs, Office docs, CSVs
├── 04-Images/            # Screenshots, photos, videos
├── 05-Archives/          # .zip, .7z, .rar
├── 06-Code-Scripts/      # .py, .js, .json, etc.
└── 99-Trash-Temp/        # Staging area for deletion

Safety First

The script never touches:

  • The script file itself
  • The log file
  • Anything outside your Downloads folder

Files aren’t deleted immediately. They sit in 99-Trash-Temp for 30 days. If you panic, you can recover them. The log tells you exactly what was moved and when.

Setup Instructions

Windows 11 (Native)

  1. Download the script from [GIST]
  2. Place it in your Downloads folder (e.g., D:\Data\Downloads\2026\)
  3. Edit the path in the script (line ~17) to match your Downloads location:$BasePath = "C:\Users\YourName\Downloads"
  4. Run once manually to test:cd D:\Data\Downloads\2026 .\Downloads-Weekly-Cleanup.ps1 -WhatIf The -WhatIf flag shows what it would do without actually doing it.
  5. Schedule it to run weekly: $Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -File D:\Data\Downloads\2026\Downloads-Weekly-Cleanup.ps1" $Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At "09:00" $Settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries Register-ScheduledTask -TaskName "Downloads Cleanup" -Action $Action -Trigger $Trigger -Settings $Settings

macOS

PowerShell works on macOS. Install it:

brew install powershell

Then follow the Windows instructions, but change paths:

$BasePath = "/Users/YourName/Downloads"

For scheduling, use launchd instead of Task Scheduler. Create ~/Library/LaunchAgents/com.downloads.cleanup.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.downloads.cleanup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/pwsh</string>
        <string>-File</string>
        <string>/Users/YourName/Downloads/Downloads-Weekly-Cleanup.ps1</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Weekday</key>
        <integer>1</integer>
        <key>Hour</key>
        <integer>9</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>

Load it:

launchctl load ~/Library/LaunchAgents/com.downloads.cleanup.plist

Linux

Install PowerShell:

# Ubuntu/Debian
sudo apt update
sudo apt install -y powershell

# Or install from Microsoft repo (recommended)
wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb"
sudo dpkg -i packages-microsoft-prod.deb
sudo apt update
sudo apt install -y powershell

Edit the script path:

$BasePath = "/home/YourName/Downloads"

Use cron for scheduling:

# Edit crontab
crontab -e

# Add line for Sunday 9 AM
0 9 * * 0 /usr/bin/pwsh -File /home/YourName/Downloads/Downloads-Weekly-Cleanup.ps1

Configurable Variables

At the top of the script, you can adjust:

param(
    [switch]$WhatIf,           # Dry run mode
    [int]$TrashDays = 30,      # Days before trash is deleted (default: 30)
    [int]$AgingDays = 60       # Days before aging to trash (default: 60)
)

More aggressive cleanup:

.\Downloads-Weekly-Cleanup.ps1 -AgingDays 30 -TrashDays 14

More lenient:

.\Downloads-Weekly-Cleanup.ps1 -AgingDays 90 -TrashDays 60

Customizing File Patterns

The script has two places you can customize:

1. Extension-to-Folder Mapping (~line 30)

$Folders = @{
    '01-Software'    = @('.exe', '.msi', '.msix', '.dmg', '.pkg')
    '03-Documents'   = @('.pdf', '.docx', '.csv', '.txt')
    '04-Images'      = @('.jpg', '.png', '.mp4', '.mov')
    # ... add your own
}

2. WordPress Patterns (~line 44)

If you work with WordPress, add plugin patterns:

$WordPressPatterns = @(
    '*placescale*.zip',
    '*woocommerce*.zip',
    '*your-plugin*.zip'
)

What the Log Looks Like

[2026-03-26 17:36:15] [INFO] Organization complete: 0 moved, 0 skipped, 0 errors
[2026-03-26 17:36:15] [WARN] Aged file moved: [03-Documents] old-invoice.pdf (79d old)
[2026-03-26 17:36:15] [WARN] Deleted: jetbrains-fonts.zip (12.49 MB) - Last modified: 01/25/2026

Everything is timestamped. If you need to recover something, you’ll know exactly when it was moved or deleted.

Why Not Just Use Any Existing Tool?

  • CCleaner/BleachBit: Too aggressive. No staging. You find out too late.
  • macOS Automator: Works, but fragile. Breaks silently.
  • Manual cleanup: You won’t do it. Would you?

This script gives you structure and safety. The 90-day lifecycle means you’re not hoarding, but you’re also not panicking.

Download

Get the script from [GIST]

Fork it. Modify it. Make it yours. The code is straightforward PowerShell—no dependencies, no external calls, no surprises.


I use this every week. It works.