🔍 Build a Desktop File Content Search App with Python & Tkinter
Source: Dev.to
File Search System Tutorial
Searching filenames is easy — searching inside files is where things get interesting.
In this tutorial we’ll build a desktop File Search System using Python, Tkinter, and ttkbootstrap that can:
- Recursively scan folders
- Search inside files (TXT, CSV, XLSX, PDF, XML)
- Support regex searches
- Show live progress, speed & ETA
- Preview matched content
- Export results to CSV
📦 Download / Clone
👉
🧰 Step 1: Install Required Libraries
Make sure you have Python 3.9+ installed, then run:
pip install ttkbootstrap xlrd PyPDF2
📁 Step 2: Import Required Modules
We’ll import modules for file handling, regex searching, threading, GUI, and file parsing.
import os
import sys
import re
import fnmatch
import threading
import time
import xlrd
import PyPDF2
import xml.etree.ElementTree as ET
import tkinter as tk
from tkinter import filedialog, messagebox
import ttkbootstrap as tb
from ttkbootstrap.constants import *
⚙️ Step 3: App Configuration
Define your app name and version in one place.
APP_NAME = "File Search System"
APP_VERSION = "1.0.1"
🪟 Step 4: Initialize the Application Window
Create the main Tkinter window and apply a modern theme.
app = tk.Tk()
style = tb.Style(theme="superhero")
app.title(f"{APP_NAME} {APP_VERSION}")
app.geometry("1230x680")
🖼 Step 5: Handle App Resources (Icons)
This ensures compatibility with PyInstaller builds.
def resource_path(file_name):
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, file_name)
ℹ️ Step 6: Create an “About” Dialog
Adds a professional touch to your app.
def show_about():
messagebox.showinfo(
f"About {APP_NAME} v{APP_VERSION}",
f"{APP_NAME} v{APP_VERSION}\n"
"Production Edition\n\n"
"A desktop utility for searching inside files.\n\n"
"✔ Regex search\n"
"✔ Multi-file support\n"
"✔ Live progress & previews\n\n"
"© 2026 Mate Technologies"
)
📋 Step 7: Add a Menu Bar
Attach the About dialog to a Help menu.
menubar = tk.Menu(app)
help_menu = tk.Menu(menubar, tearoff=0)
help_menu.add_command(label="About", command=show_about)
menubar.add_cascade(label="Help", menu=help_menu)
app.config(menu=menubar)
📂 Step 8: Build the Search Settings UI
Lets users choose a folder and a search term.
frame1 = tb.Labelframe(app, text="Search Settings", padding=10)
frame1.pack(fill="x", padx=10, pady=6)
root_path = tk.StringVar()
search_var = tk.StringVar()
regex_var = tk.BooleanVar()
tb.Label(frame1, text="Root Folder:").pack(side="left")
tb.Entry(frame1, textvariable=root_path, width=50).pack(side="left")
tb.Button(
frame1,
text="Browse",
command=lambda: root_path.set(filedialog.askdirectory())
).pack(side="left")
🧹 Step 9: Add File Filters & Controls
Users can limit file types and exclude folders.
file_filter = tk.StringVar(value="*")
exclude_folders = tk.StringVar(value="node_modules .git __pycache__")
search_btn = tb.Button(frame1, text="🔍 SEARCH", bootstyle="success")
stop_btn = tb.Button(frame1, text="🛑 STOP", bootstyle="danger-outline", state="disabled")
📊 Step 10: Progress Bar & Live Stats
Track progress, speed, ETA, and matches.
progress_var = tk.IntVar()
tb.Progressbar(app, variable=progress_var, maximum=100).pack(fill="x")
eta_lbl = tb.Label(app, text="ETA: --")
spd_lbl = tb.Label(app, text="Speed: -- files/s")
counter_lbl = tb.Label(app, text="Matches: 0")
📄 Step 11: Display Search Results
A Treeview shows file paths and preview text.
tree = tb.Treeview(app, columns=("path", "preview"), show="headings")
tree.heading("path", text="File Path")
tree.heading("preview", text="Match Preview")
tree.pack(fill="both", expand=True)
🧠 Step 12: Search Logic Helpers
File filtering
def allowed_file(name):
pats = file_filter.get().lower().split()
return "*" in pats or any(fnmatch.fnmatch(name, p) for p in pats)
Folder exclusion
def excluded_dir(path):
return any(ex in path.lower() for ex in exclude_folders.get().split())
🔍 Step 13: Read File Contents with Preview
Handles TXT, CSV, XLSX, PDF, and XML (the full version on GitHub supports all formats).
def read_file_content_with_preview(path, query, use_regex=False):
if path.endswith(".txt"):
with open(path, "r", errors="ignore") as f:
for i, line in enumerate(f, 1):
if re.search(query, line, re.I):
return True, f"Line {i}: {line[:100]}"
# (Other formats omitted for brevity)
return False, ""
🚀 Step 14: Run the Search in a Thread
Keeps the UI responsive.
def run_search():
for root, dirs, files in os.walk(root_path.get()):
# Skip excluded directories
dirs[:] = [d for d in dirs if not excluded_dir(os.path.join(root, d))]
for file in files:
if allowed_file(file):
path = os.path.join(root, file)
found, preview = read_file_content_with_preview(
path, search_var.get(), regex_var.get()
)
# Update UI (progress bar, treeview, counters) here...
You would typically start this function in a separate thread:
search_thread = threading.Thread(target=run_search, daemon=True)
search_thread.start()
🎉 That’s it!
You now have a functional desktop File Search System that can:
- Scan directories recursively
- Search inside multiple file types (TXT, CSV, XLSX, PDF, XML)
- Use plain‑text or regex queries
- Show live progress, speed, ETA, and match previews
- Export results to CSV (implementation left as an exercise)
Feel free to explore the full source code on GitHub for additional features such as PDF/XML parsing, CSV/XLSX handling, and result exporting. Happy searching!
Step 15: Export Results to CSV
def export_results():
file = filedialog.asksaveasfilename(defaultextension=".csv")
with open(file, "w", encoding="utf-8") as f:
for row in results_list:
f.write(",".join(row) + "\n")
Step 16: Start the App
app.mainloop()
✅ Final Result
You now have a fully functional desktop file‑content search tool with:
- Clean UI
- Threaded scanning
- Multiple file‑format support
- Live progress & previews
- CSV export
📦 Download / Clone from GitHub
👉
