Blog Post

5 min read Published: 2025-06-03

IMG-man_sorting_files

Introduction

Have you ever looked at a giant folder full of randomly named photos and videos and wished they could be neatly organized by date—without doing it manually?

With just a little Python code, you can automate that task—and even turn it into a simple app you can run anytime.

This beginner-friendly guide walks you through a real example that:

  • Requires no prior coding experience
  • Solves a practical, everyday problem
  • Teaches you Python step-by-step
  • Produces a tool you can share or use yourself

Why Learn Python?

Python is one of the most beginner-friendly programming languages available today. It’s:

  • Simple to read and write (it looks almost like plain English)
  • Widely used for automation, data analysis, machine learning, and more
  • Supported by a large community and countless free tools

One of the best ways to learn Python is by building something practical. This project is a great first step.

What You’ll Build

A simple Python app that automatically organizes your photos and videos into folders based on the date they were taken. The app:

  • Scans a folder for photos and videos
  • Reads the “date taken” metadata from each file
  • Creates folders like 2024/03 or 2024/03/15
  • Moves each file into the correct folder
  • Handles files with duplicate names
  • Offers a graphical interface (no command line needed)

What Is Metadata?

When you take a photo or video, your phone or camera saves extra information inside the file—such as the date, time, and sometimes even location. This data is called metadata.

For images, this metadata is often stored in a format called EXIF. This project reads that information to figure out when each photo or video was taken.

Step 1: Install Python (Recommended: Anaconda)

To get started, we recommend using Anaconda, which includes Python and many useful packages for beginners.

  • Go to anaconda.com and download the latest version.
  • Install it using the default settings.
  • Open Anaconda Prompt (you can find it by searching in your Start menu).

Step 2: Install Required Python Packages

With Anaconda Prompt open, install the two required packages by running:

pip install pymediainfo pillow
  • pillow allows the app to read image metadata
  • pymediainfo reads metadata from video files

Step 3: How the Tool Works

The tool is split into four Python files:

File Purpose
sort_pics.py Core logic for scanning folders and moving files
gui.py Graphical interface for selecting folders and sorting
utils.py Helper functions for logging and file validation
__main__.py allows to run the app with "python -m sort_pics_gui.src
### sort_pics.py - The Core Logic
- Scans thorugh a folder to find photo and video files
- reads "date taken" metadata from each file ( EXIF for images, media info for videos)
- Creates folders based on the file's creation date
- Moves each file into the appropriate folder
- Handles duplicates by renaming them (e.g., IMG_1234_1.jpg)
### gui.py - The Graphical User Interface
- This file is run to launch the app. It creates a very basic window using Python's tkinter module
- Select a folder containing all your media you want to sort
- Choose how you want your files organized (by year, month or day)
- Click a button to start the sorting process
- This file calls functions from sort_pics.py to actually process your files
IMG-sort_gui
### utils.py - Helper Functions
- contains small utility helper functions
- Log messages
- Checks if folder paths are valid
- Returns list of supported file types (image and video formats)

By separating logic, user interface and helper functions you help organizing your code across multiple files keeping your code neat, similar to different chapters and headlines in an article or a book.

Step 4: Run the App

To run the tool:

  • Open Anaconda Prompt
  • Navigate to the folder containing your project:
cd "C:\\Users\\TimeMoneyCode\\Documents\\Python\\Sort_Pics"
  • Launch the app:
python gui.py

In the window that opens:

  • Click “Select Folder” and choose the folder with your unsorted files
  • Choose how you'd like them organized:
  • Year → 2024
  • Year + Month → 2024/03
  • Year + Month + Day → 2024/03/15
  • Click “Sort Files”

The tool will move the photos and videos into the appropriate folders.

Example

Before:

Unsorted/
├── IMG_1234.jpg
├── vacation.mov
├── birthday.png

After:

Unsorted/
├── 2024/
│   └── 03/
│       ├── IMG_1234.jpg
│       ├── vacation.mov
│       └── birthday.png

If two files have the same name, the tool automatically renames them (e.g., IMG_1234_1.jpg).

Step 5: Turn It into a Standalone App

To make the app easier to run on any Windows computer (without needing Python), you can turn it into an .exe file using PyInstaller.

How to Build It:

  • Install PyInstaller:
pip install pyinstaller
  • Go to the folder containing your script:
cd "C:\\Users\\TimeMoneyCode\\Documents\\Python\\Sort_Pics"
  • Build the app:
pyinstaller --onefile --windowed gui.py

After a short time, you’ll find the executable here:

C:\Users\TimeMoneyCode\Documents\Python\Sort_Pics\dist\gui.exe

You can now run the app directly without needing Python installed on that machine.

Why This Is a Great First Project

This project teaches you how to:

  • Work with files and folders in Python
  • Extract and use real-world data (photo/video metadata)
  • Build a graphical interface
  • Automate a common, everyday task
  • Package your code into a shareable app

It’s small, useful, and achievable—exactly the kind of project that builds confidence when learning Python.

Ideas to Expand This Project

Once you’re comfortable with the basics, consider adding:

  • A progress bar to show sorting progress
  • A preview of images before sorting
  • An option to copy instead of move files
  • More organization options using more meta data information (e.g., by file type or camera model)
  • A drag-and-drop interface

Final Thoughts

IMG-python_sorting_files Learning Python doesn’t have to start with long courses or thick textbooks. It can start by solving a small, real-world problem.

This project shows that with a few lines of Python, you can take control of messy folders and save yourself time—all while learning one of the most in-demand skills today.

Whether you’re learning to automate tasks, organize your digital life, or just explore programming, this is a practical and rewarding first step.

Python Scripts

sort_pics.py:

# Created by TimeMoneyCode, 03.06.2025

# Logic for sorting pictures and videos into folders by date

from datetime import datetime
import os
from pathlib import Path
import shutil
from PIL import Image
from PIL.ExifTags import TAGS
from pymediainfo import MediaInfo

# Supported file extensions for images and videos
image_exts = {".jpg", ".jpeg", ".png", ".tiff", ".bmp", ".gif"}
video_exts = {".mp4", ".mov", ".avi", ".mkv", ".wmv", ".flv", ".webm"}


def get_image_date_taken(path):
    """
    Extract the date the image was taken from its EXIF metadata.
    Returns a string like 'YYYY:MM:DD HH:MM:SS' or None if not found.
    """
    try:
        image = Image.open(path)
        exif_data = image._getexif()
        if exif_data:
            for tag_id, value in exif_data.items():
                tag = TAGS.get(tag_id, tag_id)
                if tag == "DateTimeOriginal":
                    return value
    except Exception:
        pass
    return None


def get_video_date_taken(path):
    """
    Extract the date the video was created using pymediainfo.
    Returns a string like '2023-05-01 12:34:56' or None if not found.
    """
    try:
        media_info = MediaInfo.parse(str(path))
        for track in media_info.tracks:
            if track.track_type == "General":
                date = track.encoded_date or track.tagged_date
                if date:
                    # Remove 'UTC ' if present
                    date = date.replace("UTC ", "")
                    return date.strip()
    except Exception:
        pass
    return None


def scan_folder(folder, folder_structure):
    """
    Scan the given folder for images and videos, extract their date,
    and move them into subfolders based on the selected folder_structure.
    """
    for file in Path(folder).rglob("*"):
        if not file.is_file():
            continue  # Skip directories
        dt = None  # Will hold the datetime object
        if file.suffix.lower() in image_exts:
            date_taken = get_image_date_taken(file)
            if date_taken:
                try:
                    dt = datetime.strptime(date_taken, "%Y:%m:%d %H:%M:%S")
                except Exception:
                    pass
            print(f"Image: {file} | Date Taken: {date_taken}")
        elif file.suffix.lower() in video_exts:
            date_taken = get_video_date_taken(file)
            if date_taken:
                try:
                    if " " in date_taken and "-" in date_taken:
                        dt = datetime.strptime(date_taken, "%Y-%m-%d %H:%M:%S")
                    elif ":" in date_taken and date_taken.count(":") == 2:
                        dt = datetime.strptime(date_taken, "%Y:%m:%d %H:%M:%S")
                except Exception:
                    pass
            print(f"Video: {file} | Date Taken: {date_taken}")
        if dt:
            new_fp = create_folder(folder, dt, folder_structure)
            if new_fp:
                move_file(file, new_fp)
        else:
            print(f"Skipped (no date): {file}")


def create_folder(base_path, dt, folder_structure):
    """
    Create a folder path based on the selected structure (year, month, day).
    Returns the Path object for the new folder.
    """
    if dt:
        parts = []
        if "year" in folder_structure:
            parts.append(dt.strftime("%Y"))
        if "month" in folder_structure:
            parts.append(dt.strftime("%m"))
        if "day" in folder_structure:
            parts.append(dt.strftime("%d"))
        folder_path = Path(base_path).joinpath(*parts)
        folder_path.mkdir(parents=True, exist_ok=True)
        return folder_path
    return None


def move_file(file, date_folder):
    """
    Move the file to the target date_folder.
    If a file with the same name exists, add a number to the filename.
    """
    target_file = date_folder / file.name
    if not target_file.exists():
        shutil.move(str(file), str(target_file))
    else:
        base, ext = os.path.splitext(file.name)
        i = 1
        while True:
            new_name = f"{base}_{i}{ext}"
            new_target = date_folder / new_name
            if not new_target.exists():
                shutil.move(str(file), str(new_target))
                break
            i += 1


if __name__ == "__main__":
    # Example usage for testing (not used by the GUI)
    scan_folder("C:\\Users\\linda\\Desktop\\Sort_Pics", ["year", "month"])

gui.py:

# Created by TimeMoneyCode, 03.06.2025

# GUI for sorting pictures and videos by date using Tkinter

from tkinter import Tk, Label, Button, filedialog, messagebox, Checkbutton, IntVar
from sort_pics import scan_folder  # Import the sorting logic


class SortPicsApp:
    def __init__(self, master):
        self.master = master
        master.title("Sort Pictures and Videos")

        # Label at the top
        self.label = Label(
            master, text="Select a folder to sort pictures and videos:"
        )
        self.label.pack(pady=10)

        # Button to select the folder
        self.select_button = Button(
            master, text="Select Folder", command=self.select_folder
        )
        self.select_button.pack(pady=5)

        # Checkboxes to choose folder structure (year, month, day)
        self.year_var = IntVar(value=1)   # Checked by default
        self.month_var = IntVar(value=1)  # Checked by default
        self.day_var = IntVar(value=0)    # Unchecked by default

        self.year_cb = Checkbutton(master, text="Year", variable=self.year_var)
        self.year_cb.pack(anchor="w", padx=20)
        self.month_cb = Checkbutton(master, text="Month", variable=self.month_var)
        self.month_cb.pack(anchor="w", padx=20)
        self.day_cb = Checkbutton(master, text="Day", variable=self.day_var)
        self.day_cb.pack(anchor="w", padx=20)

        # Button to start sorting
        self.sort_button = Button(master, text="Sort Files", command=self.sort_files)
        self.sort_button.pack(pady=5)

        self.folder_path = ""  # Stores the selected folder path

    def select_folder(self):
        # Open a dialog to select a folder
        self.folder_path = filedialog.askdirectory()
        if self.folder_path:
            messagebox.showinfo(
                "Selected Folder", f"Folder selected: {self.folder_path}"
            )

    def sort_files(self):
        # Check if a folder is selected
        if not self.folder_path:
            messagebox.showwarning(
                "No Folder Selected", "Please select a folder first."
            )
            return

        # Build the folder structure list based on checkboxes
        folder_structure = []
        if self.year_var.get():
            folder_structure.append("year")
        if self.month_var.get():
            folder_structure.append("month")
        if self.day_var.get():
            folder_structure.append("day")
        if not folder_structure:
            messagebox.showwarning(
                "No Structure Selected", "Please select at least one folder level."
            )
            return

        # Call the sorting function
        try:
            scan_folder(self.folder_path, folder_structure)
            messagebox.showinfo("Success", "Files sorted successfully!")
        except Exception as e:
            messagebox.showerror("Error", f"An error occurred: {str(e)}")


# Start the GUI application
if __name__ == "__main__":
    root = Tk()
    app = SortPicsApp(root)
    root.mainloop()

utils.py:

# Created by TimeMoneyCode, 03.06.2025

def log_message(message):
    with open("app.log", "a") as log_file:
        log_file.write(f"{message}\n")


def validate_folder_path(folder_path):
    if not os.path.exists(folder_path):
        raise ValueError(f"The folder path '{folder_path}' does not exist.")
    return True


def get_supported_extensions():
    return {
        "images": {".jpg", ".jpeg", ".png", ".tiff", ".bmp", ".gif"},
        "videos": {".mp4", ".mov", ".avi", ".mkv", ".wmv", ".flv", ".webm"},
    }

main.py

# Created by TimeMoneyCode, 03.06.2025

# This file allows you to run the app with "python -m sort_pics_gui.src"

from gui import SortPicsApp
from tkinter import Tk

if __name__ == "__main__":
    root = Tk()
    app = SortPicsApp(root)
    root.mainloop()

#Python #HowTo #Other