DEV Community

Cover image for Build a Professional File Synchronization Tool in Python (FileSync PRO)
Mate Technologies
Mate Technologies

Posted on

Build a Professional File Synchronization Tool in Python (FileSync PRO)

Building your own desktop productivity tools is one of the best ways to improve your Python skills. In this tutorial, we'll build FileSync PRO, a professional folder synchronization tool with a modern UI.

It allows you to:

🔄 Sync two folders instantly

⏱ Automatically sync every 30 seconds

📁 Mirror directories

📜 See real-time activity logs

🖥 Use a modern UI with ttkbootstrap

You can download the prebuilt release here:

👉 https://github.com/rogers-cyber/FileSyncPRO/releases/tag/v1.0.0

What We Are Building

Our final tool will include:

Source → Destination folder sync

Smart file modification detection

Background threading

Auto-sync loop

Activity logging

Modern dark UI

Project Structure
filesync-pro/

├── filesync_pro.py
├── logo.ico
└── error.log
Step 1 — Install Dependencies

We only need one external library.

pip install ttkbootstrap

ttkbootstrap gives modern themes for Tkinter apps.

Step 2 — Import Required Libraries

Now let's import the modules needed for our application.

import os
import sys
import shutil
import threading
import time
import traceback
from datetime import datetime
from queue import Queue, Empty

import tkinter as tk
from tkinter import filedialog, messagebox

import ttkbootstrap as tb
from ttkbootstrap.constants import *
Enter fullscreen mode Exit fullscreen mode

What each module does
Module Purpose
os File system operations
shutil Copy files
threading Run sync in background
tkinter GUI framework
ttkbootstrap Modern UI styling
queue Thread-safe UI logging
Step 3 — Application Configuration

Define the app name and version.

APP_NAME = "FileSync PRO"
APP_VERSION = "1.0.0"
Enter fullscreen mode Exit fullscreen mode

This allows us to reuse these values throughout the UI.

Step 4 — Create the Main Window

Now we create the main Tkinter window.

app = tk.Tk()
app.title(f"{APP_NAME} {APP_VERSION}")
app.geometry("1100x620")

tb.Style("darkly")
Enter fullscreen mode Exit fullscreen mode

What this does

Creates the main app window

Sets window size

Applies the Darkly theme from ttkbootstrap

Step 5 — Create Global Variables

These variables will manage our app state.

ui_queue = Queue()

source_folder = tb.StringVar()
target_folder = tb.StringVar()

sync_running = False
auto_sync = False
Enter fullscreen mode Exit fullscreen mode

Why we use StringVar

StringVar automatically updates UI widgets when values change.

Step 6 — Utility Functions

Next we create helper functions.

Resource Path

Useful when packaging the app into .exe.

def resource_path(file_name):
    base = getattr(sys,"_MEIPASS",os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base,file_name)
Enter fullscreen mode Exit fullscreen mode

Error Logging

def log_error():
    with open("error.log","a",encoding="utf-8") as f:
        f.write(traceback.format_exc()+"\n")
Enter fullscreen mode Exit fullscreen mode

This writes any errors to error.log.

UI Logger

def log(msg):
    ui_queue.put(("log",msg))
Enter fullscreen mode Exit fullscreen mode

Instead of writing directly to the UI from threads, we send messages through a queue.

Step 7 — Build the File Sync Engine

Now we create the core logic of the tool.

def sync_folders():

    global sync_running

    if not source_folder.get() or not target_folder.get():
        messagebox.showerror("Error","Select source and target folders")
        return

    sync_running = True

    src = source_folder.get()
    dst = target_folder.get()
Enter fullscreen mode Exit fullscreen mode
log("🔄 Synchronization started")
Enter fullscreen mode Exit fullscreen mode

Validate user input

Before syncing, we check that both folders are selected.

Walk Through Files

for root, dirs, files in os.walk(src):

    if not sync_running:
        break

    rel_path = os.path.relpath(root, src)
    dst_path = os.path.join(dst, rel_path)

    if not os.path.exists(dst_path):
        os.makedirs(dst_path)
Enter fullscreen mode Exit fullscreen mode

This recreates the folder structure in the destination.

Copy Updated Files

for file in files:

    src_file = os.path.join(root,file)
    dst_file = os.path.join(dst_path,file)

    if not os.path.exists(dst_file) or \
       os.path.getmtime(src_file) > os.path.getmtime(dst_file):

        shutil.copy2(src_file,dst_file)

        log(f"✔ Synced: {file}")
Enter fullscreen mode Exit fullscreen mode

Here we only copy files if:

The file doesn't exist in destination

The source file is newer

This makes syncing fast and incremental.

Step 8 — Automatic Sync Loop

Now let's create an auto-sync feature.

def auto_sync_loop():

    global auto_sync

    auto_sync = True
    log("⏱ Auto Sync started")

    while auto_sync:

        sync_folders()

        for i in range(30):

            if not auto_sync:
                break

            time.sleep(1)

    log("🛑 Auto Sync stopped")
Enter fullscreen mode Exit fullscreen mode

This runs the sync every 30 seconds.

Stop Auto Sync

def stop_auto_sync():
    global auto_sync
    auto_sync = False
Enter fullscreen mode Exit fullscreen mode

Step 9 — Folder Selection

We allow users to browse folders.

Source Folder

def browse_source():

    folder = filedialog.askdirectory()

    if folder:
        source_folder.set(folder)
Enter fullscreen mode Exit fullscreen mode

Target Folder

def browse_target():

    folder = filedialog.askdirectory()

    if folder:
        target_folder.set(folder)
Enter fullscreen mode Exit fullscreen mode

Step 10 — Build the User Interface
App Title

title_frame = tb.Frame(app)
title_frame.pack(pady=(10,10))

tb.Label(
    title_frame,
    text=APP_NAME,
    font=("Segoe UI",26,"bold"),
    bootstyle="primary"
).pack()
Enter fullscreen mode Exit fullscreen mode

Step 11 — Control Buttons

tb.Button(
    frame_controls,
    text="🔄 Start Sync",
    bootstyle="success",
    command=lambda: threading.Thread(target=sync_folders,daemon=True).start()
).pack(side="left",padx=5)
Enter fullscreen mode Exit fullscreen mode

We use threads so the UI doesn't freeze.

Auto Sync Button

tb.Button(
    frame_controls,
    text="⏱ Start Auto Sync",
    bootstyle="warning",
    command=lambda: threading.Thread(target=auto_sync_loop,daemon=True).start()
).pack(side="left",padx=5)
Enter fullscreen mode Exit fullscreen mode

Step 12 — Activity Log Panel

A logging console helps track operations.

log_text = tk.Text(log_frame)
log_text.pack(side="left",fill="both",expand=True)

scroll = tk.Scrollbar(log_frame,command=log_text.yview)
scroll.pack(side="right",fill="y")
Enter fullscreen mode Exit fullscreen mode

Step 13 — Update UI From Background Threads

Because Tkinter is not thread-safe, we use a queue.

def process_ui_queue():

    try:

        while True:

            cmd,data = ui_queue.get_nowait()

            if cmd=="log":

                log_text.config(state="normal")
                log_text.insert("end",data+"\n")
                log_text.see("end")
                log_text.config(state="disabled")

    except Empty:
        pass

    app.after(100,process_ui_queue)
Enter fullscreen mode Exit fullscreen mode

This checks for updates every 100 ms.

Step 14 — Start the Application

Finally, we start the UI loop.

app.after(100,process_ui_queue)

app.mainloop()
Enter fullscreen mode Exit fullscreen mode

Final Result

You now have a professional desktop file synchronization tool built with Python.

Features include:

🔄 One-click folder sync

📁 Directory mirroring

⚡ Incremental file updates

⏱ Automatic background syncing

📜 Real-time logs

🖥 Modern dark UI

Download the Ready-to-Use Version

If you want the compiled executable version:

👉 https://github.com/rogers-cyber/FileSyncPRO/releases/tag/v1.0.0

Ideas for Future Improvements

You can extend this project by adding:

File hashing verification

Drag & drop folders

Sync progress bar

File filters

Cloud sync

Multi-folder sync profiles

Top comments (0)