🕵️ Progressive building a File Search Tool in Python

  

In this article, we will walk through the evolution of a console-based Python program that searches files on your filesystem. We will start with a simple version, then progressively enhance it by adding persistent interaction, performance timing, and finally the ability to open folders where search results are found.

🔗 Do you like Techelopment? Check out the website for all the details!

1. Phase 1 — Basic File Search on the Filesystem

Objective

Create a Python script that searches through a directory and its subdirectories to find files whose name contains a given keyword. The program stops after the first search.

Code

import os

root = input("Search in: ")
name = input("File name: ")

for path, _, files in os.walk(root):
    for filename in files:
        if name.lower() in filename.lower():
            print("Found:", os.path.join(path, filename))

Output Example

Search in: C:\Users\Example\Documents
File name: report
Found: C:\Users\Example\Documents\Work\report_final.pdf
Found: C:\Users\Example\Documents\Notes\meeting_report.txt

How It Works

  • os.walk(root) iterates over all directories, subdirectories, and files under root.
  • Each file is checked to see whether its name contains the user-provided substring.
  • The search is case-insensitive.
  • The script prints the full path of each matching file.

2. Phase 2 — Repeat Searches Without Restarting the Program

Objective

Modify the program to keep asking for new searches until the user types exit

Also add:

  • the ability to validate paths
  • search multiple times
  • calculate computation time

Code

import os
import time

while True:
    root = input("Search in (or type 'exit' to quit): ").strip()
    if root.lower() == "exit":
        print("Program terminated.")
        break

    if not os.path.isdir(root):
        print("Invalid path.\n")
        continue

    name = input("File name (or type 'exit' to quit): ").strip()
    if name.lower() == "exit":
        print("Program terminated.")
        break

    start_time = time.time()
    found = False

    for path, _, files in os.walk(root):
        for filename in files:
            if name.lower() in filename.lower():
                print("Found:", os.path.join(path, filename))
                found = True

    duration = time.time() - start_time

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

    print(f"Search completed in {duration:.3f} seconds.\n")

Output Example

Search in (or type 'exit' to quit): C:\Projects
File name (or type 'exit' to quit): config
Found: C:\Projects\App1\config.json
Found: C:\Projects\Library\config_template.ini
Search completed in 0.134 seconds.

Search in (or type 'exit' to quit): exit
Program terminated.

How It Works

  • The entire search process is wrapped in a while True loop so it repeats.
  • The user can type exit at any time to quit.
  • Invalid directories are handled gracefully.
  • time.time() is used to measure how long each search takes.

3. Phase 3 — Opening Folders of Search Results

Objective

After performing a search, the program should list all the unique folders where matching files were found. The user can then choose a number from the list to open the folder in the system file explorer.

Code

import os
import time
import subprocess
import platform

def open_folder(path):
    system = platform.system()

    if system == "Windows":
        os.startfile(path)
    elif system == "Darwin":  # macOS
        subprocess.Popen(["open", path])
    else:  # Linux
        subprocess.Popen(["xdg-open", path])


while True:
    root = input("Search in (or type 'exit' to quit): ").strip()
    if root.lower() == "exit":
        print("Program terminated.")
        break

    if not os.path.isdir(root):
        print("Invalid path.\n")
        continue

    name = input("File name (or type 'exit' to quit): ").strip()
    if name.lower() == "exit":
        print("Program terminated.")
        break

    print("\nSearching...")
    start_time = time.time()

    found_files = []

    for path, _, files in os.walk(root):
        for filename in files:
            if name.lower() in filename.lower():
                file_path = os.path.join(path, filename)
                found_files.append(file_path)
                print("Found:", file_path)

    duration = time.time() - start_time
    print(f"\nSearch completed in {duration:.3f} seconds.")

    if not found_files:
        print("No files found.\n")
        continue

    unique_folders = sorted({os.path.dirname(f) for f in found_files})

    while True:
        print("\nWould you like to open one of the folders?")
        print("Enter the number to open it, or type 'no' to continue.")

        for i, folder in enumerate(unique_folders, 1):
            print(f"{i}) {folder}")

        choice = input("> ").strip()

        if choice.lower() == "no":
            print("")
            break

        if choice.isdigit():
            index = int(choice)
            if 1 <= index <= len(unique_folders):
                folder = unique_folders[index - 1]
                print(f"Opening: {folder}")
                open_folder(folder)
            else:
                print("Invalid number.")
        else:
            print("Invalid input.")

Output Example

Searching...
Found: C:\Users\Example\Desktop\todo.txt
Found: C:\Users\Example\Desktop\notes.txt

Search completed in 0.041 seconds.

Would you like to open one of the folders?
Enter the number to open it, or type 'no' to continue.
1) C:\Users\Example\Desktop
> 1
Opening: C:\Users\Example\Desktop

How It Works

  • Every found file path is stored in found_files.
  • A set is used to extract unique directories, preventing duplicates.
  • The program lists folders with numbering.
  • The user chooses which folder to open by typing its number.
  • open_folder() opens folders using OS-appropriate commands:
    • Windows → os.startfile()
    • macOS → open
    • Linux → xdg-open

Conclusion

We progressively transformed a simple filesystem search script into a more robust, interactive tool capable of repeated searches, performance measurement, and folder opening. Each enhancement builds on the previous one, demonstrating how practical Python utilities can evolve step by step.

If you'd like to extend this further, you could add:

  • file opening instead of only folder opening,
  • counting results per folder,
  • exporting results to a CSV,
  • or even turning it into a GUI app.

Happy coding!



Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment