Automatically cleanup your downloads
My downloads folder is a mess. I rarely clean it, it hogs up enormous amounts of disk space, and I really only need about a fraction of the files in there to be kept.
I wrote a script to automatically clean the folder daily, it moves files between four different folders, Last week
, Old
, and Deleting soon
before finally permanently erasing them after 30 days while leaving anything in Keep
untouched.
It's a nice, quick, and neat way to keep things clean. 🙂
Before you copy it you should read the rules...
The rules
Condition | Action |
---|---|
New files < 7 days | Nothing happens. Very recent files are kept as they are. |
> 7 days | It will be moved into the Last week directory. |
> 14 days | Moved into the Old folder |
> 23 days | Moved into the Deleting soon folder |
>= 30 days | Automatically erased from your computer |
Files in Keep | Anything placed into the Keep folder is ignored by the script |
The script
import os
import shutil
import argparse
import subprocess
from datetime import datetime, timedelta
from pathlib import Path
def send_macos_notification(title, message):
applescript_cmd = f'display notification "{message}" with title "{title}"'
subprocess.run(['osascript', '-e', applescript_cmd])
def create_log_file():
logs_folder = Path("~/.logs/downloads_cleaner").expanduser()
logs_folder.mkdir(parents=True, exist_ok=True)
log_file = logs_folder / f"{datetime.now().strftime('%Y-%m-%d')}_downloads_cleaner.log"
return log_file
def remove_old_log_files(max_age_days):
logs_folder = Path("~/.logs/downloads_cleaner").expanduser()
now = datetime.now()
for log_file in logs_folder.iterdir():
if log_file.is_file():
file_age = now - datetime.fromtimestamp(log_file.stat().st_mtime)
if file_age > timedelta(days=max_age_days):
log_file.unlink()
# Command-line arguments
parser = argparse.ArgumentParser(description='Sort downloads folder by date downloaded.')
parser.add_argument('--dry-run', action='store_true', help='Perform a dry run without actually moving or deleting files')
args = parser.parse_args()
downloads_folder = Path("~/Downloads").expanduser()
last_week_folder = downloads_folder / "Last week"
old_folder = downloads_folder / "Old"
deleting_soon_folder = downloads_folder / "Deleting soon"
keep_folder = downloads_folder / "Keep"
# Create folders if they don't exist
last_week_folder.mkdir(exist_ok=True)
old_folder.mkdir(exist_ok=True)
deleting_soon_folder.mkdir(exist_ok=True)
keep_folder.mkdir(exist_ok=True)
log_file = create_log_file()
remove_old_log_files(30)
deletions = 0
moved = 0
with log_file.open('a') as log:
now = datetime.now()
# Delete files in the "Deleting soon" folder if older than 30 days
for item in deleting_soon_folder.iterdir():
if item.is_file():
file_age = now - datetime.fromtimestamp(item.stat().st_mtime)
if file_age > timedelta(days=30):
deletions += 1
if args.dry_run:
print(f'[DRY RUN] Would delete: {item}')
else:
log.write(f"{datetime.now()} - Deleting: {item}\n")
item.unlink()
# Move files to respective folders based on their age
for item in downloads_folder.iterdir():
if item.is_file():
# Check if the file is inside the "Keep" folder
if item.parent == keep_folder:
continue
# Calculate the age of the file
file_age = now - datetime.fromtimestamp(item.stat().st_mtime)
destination = None
if file_age > timedelta(days=22):
destination = deleting_soon_folder
elif file_age > timedelta(days=14):
destination = old_folder
elif file_age > timedelta(days=7):
destination = last_week_folder
if destination:
moved += 1
if args.dry_run:
print(f'[DRY RUN] Would move: {item} to {destination / item.name}')
else:
log.write(f"{datetime.now()} - Moving: {item} to {destination / item.name}\n")
shutil.move(str(item), destination / item.name)
# Send macOS notification
notification_message = f"{deletions} deleted, {moved} moved."
send_macos_notification("Downloads cleaner", notification_message)
How to use it
You'll need Python, the script has also been written for my mac so Windows and Linux users will need to tweak the location of their downloads and snip out the notification function.
To test the script you can pass the --dry-run
parameter to see what it would have done without touching anything.
python3 downloads_cleaner.py --dry-run
To check on any files that have been moved or deleted you can check the log file written to ~/.logs/downloads_cleaner
.
cat ~/.logs/downloads_cleaner/2021-04-30_downloads_cleaner.log
Automating it
The next step is to automate this thing, if you're on unix then the obvious choice is a cron job. I've set mine to run daily at 9am.
crontab -e
0 9 * * * python3 ~/scripts/downloads_cleaner.py
If you're on Windows, Task Scheduler is your friend.
Mac users
If you're on macOS may wake up the next morning to find a message for you waiting in your terminal, you'll need to give cron access to your downloads folder. In order to do this...
- Go to System Preferences > Security & Privacy > Privacy > Full Disk Access
- Click the lock icon to make changes
- Click the + icon and add crontab to the list
- Restart your computer
And that's it. Thanks for reading. 🙂