Python Automation Scripts for Beginners: 10 Scripts That Save Hours Every Week

Python Automation Scripts for Beginners: 10 Scripts That Save Hours Every Week

What if you could eliminate two hours of repetitive computer tasks every single day? That is exactly what Python automation scripts for beginners can do.

Python is the most popular language for automation because of its readable syntax, massive library ecosystem, and ability to interact with files, emails, websites, and APIs with just a few lines of code. You do not need years of experience to start automating. If you can write a basic Python function, you can automate real tasks today.

This guide gives you 10 complete, ready-to-use automation scripts. Each one solves a real problem, includes full source code, and teaches you a different automation skill.


Why Python for Automation in 2026?

Python dominates the automation space for several clear reasons:

  • Built-in standard library handles files, folders, emails, and system operations without installing anything
  • Third-party packages like requests, schedule, and openpyxl extend capabilities infinitely
  • Cross-platform compatibility means scripts work on Windows, macOS, and Linux
  • AI integration allows you to add intelligent decision-making to your automation workflows

Whether you want to automate your personal workflow or build automation tools for your job, these scripts give you the foundation.


Setting Up Your Automation Environment

Before writing any scripts, set up a clean project environment:

# Create a project directory
mkdir python_automation
cd python_automation

# Create a virtual environment (recommended)
python -m venv .venv

# Activate it
# macOS/Linux:
source .venv/bin/activate
# Windows:
.venv\Scripts\activate

# Install common automation libraries
pip install requests schedule openpyxl python-dotenv Pillow PyPDF2

For a detailed guide on virtual environments, see our complete venv Python tutorial.


Script 1: Automatic File Organizer

Problem: Your Downloads folder is a chaotic mess of files.
Solution: A script that automatically sorts files into categorized subfolders.

"""
file_organizer.py - Automatically sort files by type into organized folders.
"""

import os
import shutil
from pathlib import Path
from datetime import datetime

# Configuration: Define file categories and their extensions
FILE_CATEGORIES = {
    "Images": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg", ".ico"],
    "Documents": [".pdf", ".doc", ".docx", ".txt", ".xlsx", ".xls", ".pptx", ".csv"],
    "Videos": [".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv"],
    "Audio": [".mp3", ".wav", ".flac", ".aac", ".ogg", ".wma"],
    "Archives": [".zip", ".rar", ".7z", ".tar", ".gz", ".bz2"],
    "Code": [".py", ".js", ".html", ".css", ".java", ".cpp", ".json", ".xml"],
    "Installers": [".exe", ".msi", ".dmg", ".deb", ".rpm"],
}


def get_category(file_extension):
    """Determine which category a file belongs to based on its extension."""
    for category, extensions in FILE_CATEGORIES.items():
        if file_extension.lower() in extensions:
            return category
    return "Other"


def organize_folder(target_folder):
    """
    Scan the target folder and move each file into a categorized subfolder.
    Skips directories and hidden files.
    """
    target_path = Path(target_folder)

    if not target_path.exists():
        print(f"Error: Folder '{target_folder}' does not exist.")
        return

    moved_count = 0
    skipped_count = 0

    print(f"\nOrganizing: {target_path}")
    print("-" * 50)

    for item in target_path.iterdir():
        # Skip directories, hidden files, and this script itself
        if item.is_dir() or item.name.startswith("."):
            skipped_count += 1
            continue

        # Determine the category
        category = get_category(item.suffix)

        # Create the category subfolder if it does not exist
        category_folder = target_path / category
        category_folder.mkdir(exist_ok=True)

        # Handle filename conflicts
        destination = category_folder / item.name
        if destination.exists():
            stem = item.stem
            suffix = item.suffix
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            destination = category_folder / f"{stem}_{timestamp}{suffix}"

        # Move the file
        shutil.move(str(item), str(destination))
        print(f"  Moved: {item.name} -> {category}/")
        moved_count += 1

    print(f"\nDone! Moved {moved_count} files. Skipped {skipped_count} items.")


if __name__ == "__main__":
    # Default to Downloads folder - change this path as needed
    downloads_folder = str(Path.home() / "Downloads")
    organize_folder(downloads_folder)

How to use: Run it manually whenever your Downloads folder gets messy, or set it up as a scheduled task (see Script 10).


Script 2: Bulk File Renamer

Problem: You have 200 photos named “IMG_20260101_123456.jpg” and want them renamed to “vacation_001.jpg”, “vacation_002.jpg”, etc.

"""
bulk_renamer.py - Rename multiple files with a consistent naming pattern.
"""

import os
from pathlib import Path


def bulk_rename(folder, prefix, start_number=1, extension_filter=None):
    """
    Rename all files in a folder with a sequential pattern.

    Args:
        folder: Path to the folder containing files
        prefix: New name prefix (e.g., "vacation")
        start_number: Starting number for the sequence
        extension_filter: Only rename files with this extension (e.g., ".jpg")
    """
    folder_path = Path(folder)

    if not folder_path.exists():
        print(f"Error: Folder '{folder}' not found.")
        return

    # Get and sort files
    files = sorted(folder_path.iterdir())

    if extension_filter:
        files = [f for f in files if f.suffix.lower() == extension_filter.lower()]
    else:
        files = [f for f in files if f.is_file()]

    if not files:
        print("No matching files found.")
        return

    print(f"Renaming {len(files)} files with prefix '{prefix}'...\n")

    # Determine zero-padding width based on total file count
    padding = len(str(len(files) + start_number))

    renamed_count = 0
    for index, file_path in enumerate(files, start=start_number):
        new_name = f"{prefix}_{str(index).zfill(padding)}{file_path.suffix}"
        new_path = file_path.parent / new_name

        file_path.rename(new_path)
        print(f"  {file_path.name} -> {new_name}")
        renamed_count += 1

    print(f"\nRenamed {renamed_count} files successfully.")


if __name__ == "__main__":
    # Example usage
    target = input("Enter folder path: ").strip()
    name_prefix = input("Enter new name prefix: ").strip()
    ext = input("Filter by extension (e.g., .jpg) or press Enter for all: ").strip()

    bulk_rename(target, name_prefix, extension_filter=ext if ext else None)

Script 3: PDF Merger

Problem: You need to combine multiple PDF files into a single document.

"""
pdf_merger.py - Combine multiple PDF files into one document.
Requires: pip install PyPDF2
"""

from PyPDF2 import PdfMerger
from pathlib import Path


def merge_pdfs(folder, output_name="merged_output.pdf"):
    """Merge all PDF files in a folder into a single PDF."""
    folder_path = Path(folder)

    # Find all PDFs and sort them alphabetically
    pdf_files = sorted(folder_path.glob("*.pdf"))

    if not pdf_files:
        print("No PDF files found in the specified folder.")
        return

    print(f"Found {len(pdf_files)} PDF files to merge:\n")

    merger = PdfMerger()

    for pdf in pdf_files:
        print(f"  Adding: {pdf.name}")
        merger.append(str(pdf))

    output_path = folder_path / output_name
    merger.write(str(output_path))
    merger.close()

    print(f"\nMerged successfully into: {output_path}")


if __name__ == "__main__":
    folder = input("Enter folder containing PDFs: ").strip()
    merge_pdfs(folder)

Script 4: Image Resizer and Compressor

Problem: You need to resize 50 images for your website to reduce load times.

"""
image_resizer.py - Batch resize and compress images for web use.
Requires: pip install Pillow
"""

from PIL import Image
from pathlib import Path


def resize_images(input_folder, output_folder, max_width=1200, quality=85):
    """
    Resize all images in a folder to a maximum width while maintaining aspect ratio.
    Saves compressed versions to the output folder.
    """
    input_path = Path(input_folder)
    output_path = Path(output_folder)
    output_path.mkdir(parents=True, exist_ok=True)

    image_extensions = {".jpg", ".jpeg", ".png", ".webp", ".bmp"}
    images = [f for f in input_path.iterdir() if f.suffix.lower() in image_extensions]

    if not images:
        print("No images found.")
        return

    print(f"Processing {len(images)} images (max width: {max_width}px, quality: {quality}%)...\n")

    total_saved = 0

    for img_path in images:
        with Image.open(img_path) as img:
            original_size = img_path.stat().st_size

            # Calculate new dimensions maintaining aspect ratio
            if img.width > max_width:
                ratio = max_width / img.width
                new_height = int(img.height * ratio)
                img = img.resize((max_width, new_height), Image.LANCZOS)

            # Save with compression
            output_file = output_path / img_path.name

            if img_path.suffix.lower() in {".jpg", ".jpeg"}:
                img.save(output_file, "JPEG", quality=quality, optimize=True)
            elif img_path.suffix.lower() == ".png":
                img.save(output_file, "PNG", optimize=True)
            else:
                img.save(output_file, quality=quality)

            new_size = output_file.stat().st_size
            saved = original_size - new_size
            total_saved += saved

            print(f"  {img_path.name}: {original_size//1024}KB -> {new_size//1024}KB (saved {saved//1024}KB)")

    print(f"\nTotal space saved: {total_saved//1024}KB ({total_saved//1048576}MB)")


if __name__ == "__main__":
    input_dir = input("Input folder: ").strip()
    output_dir = input("Output folder: ").strip()
    resize_images(input_dir, output_dir)

Script 5: CSV Report Generator

Problem: You have raw data in a CSV and need to generate a formatted summary report.

"""
csv_reporter.py - Generate summary reports from CSV data files.
"""

import csv
from pathlib import Path
from collections import Counter
from datetime import datetime


def generate_report(csv_file):
    """Read a CSV file and produce a summary report."""
    file_path = Path(csv_file)

    if not file_path.exists():
        print(f"Error: File '{csv_file}' not found.")
        return

    with open(file_path, "r", newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        rows = list(reader)

    if not rows:
        print("CSV file is empty.")
        return

    columns = list(rows[0].keys())

    print(f"\n{'='*60}")
    print(f"  CSV REPORT: {file_path.name}")
    print(f"  Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
    print(f"{'='*60}")
    print(f"\n  Total rows: {len(rows)}")
    print(f"  Columns: {', '.join(columns)}")

    # Analyze each column
    print(f"\n  COLUMN ANALYSIS:")
    print(f"  {'-'*50}")

    for col in columns:
        values = [row[col] for row in rows if row[col].strip()]
        unique_count = len(set(values))
        empty_count = len(rows) - len(values)

        print(f"\n  [{col}]")
        print(f"    Unique values: {unique_count}")
        print(f"    Empty/missing: {empty_count}")

        # Try numeric analysis
        try:
            numeric_values = [float(v) for v in values]
            avg = sum(numeric_values) / len(numeric_values)
            print(f"    Min: {min(numeric_values)}, Max: {max(numeric_values)}, Avg: {avg:.2f}")
        except ValueError:
            # Non-numeric: show top 5 most common values
            most_common = Counter(values).most_common(5)
            print(f"    Top values: {', '.join(f'{v}({c})' for v, c in most_common)}")

    print(f"\n{'='*60}\n")


if __name__ == "__main__":
    file = input("Enter CSV file path: ").strip()
    generate_report(file)

Script 6: Automated Email Sender

Problem: You need to send personalized emails to a list of contacts.

"""
email_sender.py - Send personalized emails from a template.
Uses environment variables for credentials (never hardcode passwords).
"""

import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart


def send_email(recipient, subject, body, sender_email, sender_password):
    """Send a single email using Gmail SMTP."""
    msg = MIMEMultipart()
    msg["From"] = sender_email
    msg["To"] = recipient
    msg["Subject"] = subject
    msg.attach(MIMEText(body, "html"))

    try:
        with smtplib.SMTP("smtp.gmail.com", 587) as server:
            server.starttls()
            server.login(sender_email, sender_password)
            server.send_message(msg)
        print(f"  Sent to: {recipient}")
        return True
    except Exception as e:
        print(f"  Failed for {recipient}: {e}")
        return False


def send_bulk_emails(contacts, subject_template, body_template):
    """
    Send personalized emails to a list of contacts.

    contacts: List of dicts with 'name' and 'email' keys
    subject_template: Subject with {name} placeholder
    body_template: HTML body with {name} placeholder
    """
    # Load credentials from environment variables (NEVER hardcode these)
    sender_email = os.environ.get("SENDER_EMAIL")
    sender_password = os.environ.get("SENDER_APP_PASSWORD")

    if not sender_email or not sender_password:
        print("Error: Set SENDER_EMAIL and SENDER_APP_PASSWORD environment variables.")
        print("For Gmail, use an App Password (not your regular password).")
        return

    print(f"\nSending {len(contacts)} emails...\n")

    success_count = 0
    for contact in contacts:
        subject = subject_template.format(name=contact["name"])
        body = body_template.format(name=contact["name"])

        if send_email(contact["email"], subject, body, sender_email, sender_password):
            success_count += 1

    print(f"\nDone: {success_count}/{len(contacts)} emails sent successfully.")


if __name__ == "__main__":
    # Example contacts list
    contacts = [
        {"name": "Alice", "email": "alice@example.com"},
        {"name": "Bob", "email": "bob@example.com"},
    ]

    subject = "Hello {name} - Quick Update"
    body = """
    <h2>Hi {name},</h2>
    <p>This is an automated email sent from a Python script.</p>
    <p>Best regards,<br>Your Python Automation</p>
    """

    send_bulk_emails(contacts, subject, body)

Security note: Never put passwords in your code. Use environment variables or a .env file with python-dotenv.


Script 7: Website Uptime Monitor

Problem: You want to know immediately when your website goes down.

"""
uptime_monitor.py - Check if websites are responding and log downtime.
Requires: pip install requests
"""

import requests
import time
from datetime import datetime
from pathlib import Path


URLS_TO_MONITOR = [
    "https://pythonforbegineers.com",
    "https://google.com",
    "https://github.com",
]

LOG_FILE = "uptime_log.txt"
CHECK_INTERVAL = 300  # seconds (5 minutes)


def check_url(url, timeout=10):
    """Check if a URL is responding. Returns (status_code, response_time) or (None, None) on failure."""
    try:
        start = time.time()
        response = requests.get(url, timeout=timeout)
        elapsed = time.time() - start
        return response.status_code, round(elapsed, 2)
    except requests.RequestException:
        return None, None


def log_result(url, status, response_time):
    """Log the check result to a file."""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    if status:
        entry = f"[{timestamp}] {url} - Status: {status} - Response: {response_time}s"
    else:
        entry = f"[{timestamp}] {url} - DOWN - No response"

    with open(LOG_FILE, "a") as f:
        f.write(entry + "\n")

    print(entry)


def run_monitor():
    """Continuously monitor all URLs at the specified interval."""
    print(f"Monitoring {len(URLS_TO_MONITOR)} URLs every {CHECK_INTERVAL} seconds...")
    print(f"Logging to: {LOG_FILE}")
    print("Press Ctrl+C to stop.\n")

    try:
        while True:
            for url in URLS_TO_MONITOR:
                status, response_time = check_url(url)
                log_result(url, status, response_time)

            print(f"  Next check in {CHECK_INTERVAL} seconds...\n")
            time.sleep(CHECK_INTERVAL)

    except KeyboardInterrupt:
        print("\nMonitoring stopped.")


if __name__ == "__main__":
    run_monitor()

Script 8: Duplicate File Finder

Problem: Your hard drive is full but you suspect there are many duplicate files wasting space.

"""
duplicate_finder.py - Find and report duplicate files based on content hash.
"""

import hashlib
from pathlib import Path
from collections import defaultdict


def get_file_hash(file_path, chunk_size=8192):
    """Calculate MD5 hash of a file's contents."""
    hasher = hashlib.md5()
    with open(file_path, "rb") as f:
        while chunk := f.read(chunk_size):
            hasher.update(chunk)
    return hasher.hexdigest()


def find_duplicates(folder, min_size_kb=1):
    """
    Find duplicate files in a folder (recursive).
    Returns groups of files with identical content.
    """
    folder_path = Path(folder)

    if not folder_path.exists():
        print(f"Error: Folder '{folder}' not found.")
        return {}

    print(f"Scanning: {folder_path} (min size: {min_size_kb}KB)...\n")

    # Group files by size first (fast pre-filter)
    size_groups = defaultdict(list)
    file_count = 0

    for file_path in folder_path.rglob("*"):
        if file_path.is_file() and file_path.stat().st_size >= min_size_kb * 1024:
            size_groups[file_path.stat().st_size].append(file_path)
            file_count += 1

    print(f"  Scanned {file_count} files.")

    # Hash only files with matching sizes
    hash_groups = defaultdict(list)
    hashed_count = 0

    for size, files in size_groups.items():
        if len(files) > 1:  # Only hash if multiple files share the same size
            for file_path in files:
                file_hash = get_file_hash(file_path)
                hash_groups[file_hash].append(file_path)
                hashed_count += 1

    print(f"  Hashed {hashed_count} potential duplicates.\n")

    # Filter to only groups with actual duplicates
    duplicates = {h: files for h, files in hash_groups.items() if len(files) > 1}

    if not duplicates:
        print("No duplicates found!")
        return {}

    # Report findings
    total_wasted = 0
    print(f"  Found {len(duplicates)} groups of duplicate files:\n")

    for group_num, (file_hash, files) in enumerate(duplicates.items(), 1):
        file_size = files[0].stat().st_size
        wasted = file_size * (len(files) - 1)
        total_wasted += wasted

        print(f"  Group {group_num} ({file_size // 1024}KB each, {len(files)} copies):")
        for f in files:
            print(f"    {f}")
        print()

    print(f"  Total wasted space: {total_wasted // 1048576}MB")
    return duplicates


if __name__ == "__main__":
    target = input("Enter folder to scan: ").strip()
    find_duplicates(target)

Script 9: Text File Search (grep Alternative)

Problem: You need to find a specific string across hundreds of code files in a project.

"""
text_search.py - Search for text patterns across files in a directory.
"""

from pathlib import Path
import re


def search_files(folder, pattern, extensions=None, case_sensitive=False):
    """
    Search for a text pattern in all files within a folder.

    Args:
        folder: Directory to search
        pattern: Text or regex pattern to find
        extensions: List of file extensions to include (e.g., [".py", ".txt"])
        case_sensitive: Whether the search is case-sensitive
    """
    folder_path = Path(folder)

    if not folder_path.exists():
        print(f"Error: Folder '{folder}' not found.")
        return

    flags = 0 if case_sensitive else re.IGNORECASE
    compiled_pattern = re.compile(pattern, flags)

    total_matches = 0
    files_with_matches = 0

    print(f"\nSearching for: '{pattern}' in {folder_path}\n")

    for file_path in folder_path.rglob("*"):
        if not file_path.is_file():
            continue

        # Filter by extension if specified
        if extensions and file_path.suffix.lower() not in extensions:
            continue

        # Skip binary files
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                lines = f.readlines()
        except (UnicodeDecodeError, PermissionError):
            continue

        file_matches = []
        for line_num, line in enumerate(lines, 1):
            if compiled_pattern.search(line):
                file_matches.append((line_num, line.strip()))

        if file_matches:
            files_with_matches += 1
            total_matches += len(file_matches)

            relative_path = file_path.relative_to(folder_path)
            print(f"  {relative_path}:")
            for line_num, content in file_matches[:5]:  # Show first 5 matches per file
                print(f"    Line {line_num}: {content[:100]}")
            if len(file_matches) > 5:
                print(f"    ... and {len(file_matches) - 5} more matches")
            print()

    print(f"Results: {total_matches} matches in {files_with_matches} files.")


if __name__ == "__main__":
    folder = input("Search in folder: ").strip()
    pattern = input("Search pattern: ").strip()
    ext_input = input("File extensions (comma-separated, or Enter for all): ").strip()

    extensions = [e.strip() if e.startswith(".") else f".{e.strip()}" 
                  for e in ext_input.split(",") if e.strip()] if ext_input else None

    search_files(folder, pattern, extensions)

Script 10: Task Scheduler (Run Scripts Automatically)

Problem: You want scripts to run automatically at specific times without cron jobs.

"""
scheduler.py - Schedule Python scripts to run at specific times or intervals.
Requires: pip install schedule
"""

import schedule
import time
from datetime import datetime


def daily_backup():
    """Example task: could call your file organizer or any other script."""
    print(f"[{datetime.now().strftime('%H:%M:%S')}] Running daily backup...")
    # Import and call your other scripts here
    # from file_organizer import organize_folder
    # organize_folder("/path/to/downloads")


def hourly_check():
    """Example task: website monitoring or data sync."""
    print(f"[{datetime.now().strftime('%H:%M:%S')}] Running hourly check...")


def weekly_report():
    """Example task: generate and email a weekly report."""
    print(f"[{datetime.now().strftime('%H:%M:%S')}] Generating weekly report...")


# Schedule configuration
schedule.every().day.at("09:00").do(daily_backup)
schedule.every(1).hours.do(hourly_check)
schedule.every().monday.at("08:00").do(weekly_report)


if __name__ == "__main__":
    print("Scheduler started. Press Ctrl+C to stop.")
    print(f"Scheduled jobs: {len(schedule.get_jobs())}")

    for job in schedule.get_jobs():
        print(f"  - {job}")

    print()

    try:
        while True:
            schedule.run_pending()
            time.sleep(60)  # Check every minute
    except KeyboardInterrupt:
        print("\nScheduler stopped.")

Combining Scripts: Building a Complete Automation System

The real power of Python automation scripts for beginners comes when you combine multiple scripts into a workflow. Here is an example that chains several scripts together:

"""
morning_routine.py - Run multiple automation tasks as a daily workflow.
"""

from file_organizer import organize_folder
from uptime_monitor import check_url, URLS_TO_MONITOR
from pathlib import Path


def morning_workflow():
    """Execute the complete morning automation routine."""
    print("=" * 50)
    print("  MORNING AUTOMATION ROUTINE")
    print("=" * 50)

    # Step 1: Organize downloads
    print("\n[Step 1] Organizing Downloads folder...")
    organize_folder(str(Path.home() / "Downloads"))

    # Step 2: Check website status
    print("\n[Step 2] Checking website status...")
    for url in URLS_TO_MONITOR:
        status, response_time = check_url(url)
        if status == 200:
            print(f"  {url}: OK ({response_time}s)")
        else:
            print(f"  {url}: PROBLEM (status: {status})")

    # Step 3: Generate any pending reports
    print("\n[Step 3] Checking for pending reports...")
    print("  No pending reports today.")

    print("\n" + "=" * 50)
    print("  Morning routine complete!")
    print("=" * 50)


if __name__ == "__main__":
    morning_workflow()

FAQ

What is the easiest Python automation script for a complete beginner?

The file organizer (Script 1) is the easiest starting point. It only uses Python’s built-in os, shutil, and pathlib modules with no external dependencies. You can see immediate results in your own Downloads folder, which makes the learning process tangible.

Do I need to learn a framework to automate tasks with Python?

No. All 10 scripts in this guide use only Python’s standard library plus a few lightweight packages. You do not need Django, Flask, or any web framework for automation. The os, pathlib, shutil, smtplib, and csv modules handle 80% of automation tasks.

How do I run Python automation scripts on a schedule?

For simple scheduling within Python, use the schedule library (Script 10). For system-level scheduling, use cron on Linux/macOS (crontab -e) or Task Scheduler on Windows. For cloud-based scheduling, use services like GitHub Actions or AWS Lambda.

Can Python automate tasks in Microsoft Excel?

Yes. The openpyxl library reads, writes, and modifies Excel files (.xlsx) programmatically. You can automate report generation, data formatting, chart creation, and formula insertion without ever opening Excel.

Is it legal to automate web interactions with Python?

It depends on the website. Always check a site’s Terms of Service and robots.txt file before automating interactions. Automating your own accounts and workflows is generally fine. Scraping copyrighted content or bypassing authentication is not. See our Python web scraping tutorial for ethical scraping guidelines.


Next Steps

Start with Script 1 (File Organizer) today. Run it on your actual Downloads folder and watch the magic happen. Once you see the results, you will be motivated to implement the rest.

For more beginner project ideas that combine automation with other skills, check out:
Python Project Ideas for Beginners 2026
How to Build a Python Quiz App Step by Step


Last updated: July 2026

Leave a Comment

Scroll to Top