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

A practical PowerShell script that auto-organizes your Downloads folder and safely cleans up old files without the panic of accidental deletion. Works on Windows, macOS, and Linux.

Author: Ruhani Rabin
Canonical: https://rabin.blog/auto-organize-downloads-folder-powershell-script-windows-mac-linux/
Published: 2026-08-07T08:28:57.000Z
Updated: 2026-08-24T14:37:18.000Z

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)

```plaintext
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

```plaintext
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\]](https://gist.github.com/ruhanirabin/7849c1e4954784a0a629d761f2274622)**
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:

```plaintext
brew install powershell
```

Then follow the Windows instructions, but change paths:

```plaintext
$BasePath = "/Users/YourName/Downloads"
```

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

```plaintext
<?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:

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

### Linux

Install PowerShell:

```plaintext
# 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:

```plaintext
$BasePath = "/home/YourName/Downloads"
```

Use `cron` for scheduling:

```plaintext
# 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:

```plaintext
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:**

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

**More lenient:**

```plaintext
.\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)

```plaintext
$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:

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

## What the Log Looks Like

```plaintext
[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 **[\[](https://gist.github.com/ruhanirabin/7849c1e4954784a0a629d761f2274622) [GIST](https://gist.github.com/ruhanirabin/7849c1e4954784a0a629d761f2274622) [\]](https://gist.github.com/ruhanirabin/7849c1e4954784a0a629d761f2274622)**

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.

## Related reading

* [Back up a Dockerized n8n instance to GitHub or GitLab](https://rabin.blog/automated-backups-dockerized-n8n-sqlite-gitlab-github/)
* [Back up and restore Home Assistant with Git](https://rabin.blog/how-to-automatically-backup-restore-home-assistant-github-gitlab/)
