Build a Command-Line Tool in Python That Organizes Your Downloads Folder
Introduction
Your Downloads folder is often a dumping ground for PDFs, ZIPs, images, and all sorts of random files. Over time, it becomes a digital junk drawer. What if you could run a simple Python script that organizes this chaos automatically? In this post, we’ll build a command-line interface (CLI) tool using Python to scan your Downloads directory and sort files by type or date — all configurable via command-line arguments.
Section 1: Setting Up the CLI with Argparse
We’ll start by designing a flexible command-line interface using Python’s built-in argparse module. This will let users specify options like target directory, sorting method, and more.
import argparse
def get_args():
parser = argparse.ArgumentParser(description='Organize Downloads folder by file type or date.')
parser.add_argument('--path', type=str, default='~/Downloads', help='Path to the Downloads folder')
parser.add_argument('--mode', type=str, choices=['type', 'date'], default='type', help='Sorting mode: type or date')
parser.add_argument('--dry-run', action='store_true', help='Preview what will be moved without making changes')
return parser.parse_args()
if __name__ == '__main__':
args = get_args()
print(args)
Run this script with options like python organize.py --mode date --dry-run. The dry-run flag is crucial for testing safely without moving files accidentally.
Section 2: Scanning and Categorizing Files
Next, let’s detect all files in the target folder and categorize them. We’ll use the os and pathlib modules for cross-platform file handling.
import os
from pathlib import Path
def scan_files(base_path):
base = Path(base_path).expanduser()
files = [f for f in base.iterdir() if f.is_file()]
return files
def categorize_by_type(files):
categories = {}
for f in files:
ext = f.suffix.lower().lstrip('.') or 'no_extension'
categories.setdefault(ext, []).append(f)
return categories
files = scan_files('~/Downloads')
file_groups = categorize_by_type(files)
for ext, group in file_groups.items():
print(ext, len(group))
This code organizes files into a dictionary keyed by file type (extensions). Developers can customize this logic — for example, grouping certain extensions together like .jpg, .png, and .gif under an Images category.
Section 3: Moving Files Safely
Now that we’ve grouped files, let’s move them into subfolders. We’ll ensure that operations are idempotent and avoid overwriting existing files.
import shutil
def move_files(groups, base_path, dry_run=False):
base = Path(base_path).expanduser()
for category, files in groups.items():
target_dir = base / category
if not target_dir.exists():
if not dry_run:
target_dir.mkdir(parents=True)
for f in files:
dest = target_dir / f.name
if dest.exists():
print(f'Skipped: {f.name} already exists')
continue
if dry_run:
print(f'[DRY RUN] Would move {f} -> {target_dir}')
else:
shutil.move(str(f), str(dest))
print(f'Moved: {f.name} -> {category}/')
The above ensures no accidental overwriting and supports a dry-run mode for safety. For performance, this simple approach works well up to thousands of files.
Section 4: Adding Sorting by Date
Sorting by modification date can help organize older files into folders like 2024-01 or 2023-12. Here’s how to do it:
from datetime import datetime
def categorize_by_date(files):
categories = {}
for f in files:
ts = f.stat().st_mtime
date_folder = datetime.fromtimestamp(ts).strftime('%Y-%m')
categories.setdefault(date_folder, []).append(f)
return categories
By calling categorize_by_date() instead of categorize_by_type() based on args.mode, our CLI becomes flexible:
if args.mode == 'type':
groups = categorize_by_type(files)
else:
groups = categorize_by_date(files)
move_files(groups, args.path, args.dry_run)
Section 5: Packaging and Extending the CLI
Once the logic works, you can convert this script into a proper CLI command installed via setuptools or poetry. In setup.py:
from setuptools import setup, find_packages
setup(
name='downloads-organizer',
version='1.0',
packages=find_packages(),
entry_points={
'console_scripts': [
'organize-downloads=organizer.main:main'
],
},
)
This lets you install your tool globally and run it with organize-downloads --mode type. You can also add logging, parallel file processing, or even integrate a configuration file for user preferences.
Conclusion
In this post, you built a Python CLI tool that automates file organization using argparse, pathlib, and some smart logic. This approach demonstrates how Python excels at automating everyday tasks, and the CLI framework makes it extensible for future enhancements. Try scheduling it with cron or Windows Task Scheduler to keep your Downloads folder organized automatically.
Useful links:


