![]() |
The evolution of our local search tool continues 😄 (if you missed the previous episodes you can take a look here and here).
In this episode we will see how to integrate the search functionality into the contents of files 📝 (and not just the file name).
Objective
The goal of this evolution of the tool is to extend the search to the file content so as to identify the keyword not only in the file or folder name but also within the text of the files.
We must therefore give the user the ability to choose how to perform the search:
-
Only in the name (file + folders) — current behavior of the tool developed in previous articles
-
In the contents of the files — in addition to searching in the name, the program must open the files and search their contents
The extension is completely transparent to the user: just enter a name and the program searches everywhere, in folders, files and file contents.
Code
import os
import time
import subprocess
import platform
# -----------------------------
# OPEN FOLDER
# -----------------------------
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])
# -----------------------------
# OPEN FILE
# -----------------------------
def open_file(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])
# -----------------------------
# MAIN LOOP
# -----------------------------
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("Search term (file/folder name or content): ").strip()
if name.lower() == "exit":
print("Program terminated.")
break
# -----------------------------
# CHOOSE SEARCH MODE
# -----------------------------
print("\nChoose search mode:")
print("1) Search only in file/folder NAMES")
print("2) Search also inside FILE CONTENTS")
while True:
mode = input("> ").strip()
if mode in ("1", "2"):
break
print("Invalid choice. Type 1 or 2.")
search_in_content = (mode == "2")
print("\nSearching...")
start_time = time.time()
found_paths = [] # files + folders
found_files = [] # only files (for opening later)
found_folders = [] # only folders (actual folders found)
# -----------------------------
# SEARCH EXECUTION
# -----------------------------
for path, dirs, files in os.walk(root):
# ---- SEARCH IN FOLDER NAMES ----
for dirname in dirs:
if name.lower() in dirname.lower():
folder_path = os.path.join(path, dirname)
found_paths.append(folder_path)
found_folders.append(folder_path)
print("📁 Found folder:", folder_path)
# ---- SEARCH IN FILE NAMES ----
for filename in files:
if name.lower() in filename.lower():
file_path = os.path.join(path, filename)
found_paths.append(file_path)
found_files.append(file_path)
print("📄 Found file:", file_path)
# ---- SEARCH IN FILE CONTENTS (optional) ----
if search_in_content:
for filename in files:
file_path = os.path.join(path, filename)
try:
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
for line in f:
if name.lower() in line.lower():
if file_path not in found_paths:
found_paths.append(file_path)
found_files.append(file_path)
print("📝 Found in content:", file_path)
break
except:
pass
duration = time.time() - start_time
print(f"\nSearch completed in {duration:.3f} seconds.")
if not found_paths:
print("No results found.\n")
continue
# -----------------------------
# UNIQUE FOLDERS FOR THE FINAL MENU
# -----------------------------
unique_folders = set()
for p in found_paths:
if os.path.isdir(p):
unique_folders.add(p) # actual folder found
else:
unique_folders.add(os.path.dirname(p)) # parent folder of file
unique_folders = sorted(unique_folders)
found_files = sorted(found_files)
# -----------------------------
# FINAL MENU FOR OPENING ITEMS
# -----------------------------
while True:
print("\nWould you like to open something?")
print("1) Open a folder")
print("2) Open a file")
print("no) Continue to new search\n")
choice = input("> ").strip().lower()
if choice == "no":
print("")
break
# ---- OPEN FOLDERS ----
if choice == "1":
print("\n=== FOLDERS ===")
for i, folder in enumerate(unique_folders, 1):
print(f"{i}) 📁 {folder}")
sel = input("\nChoose a folder number (or 'no'): ").strip()
if sel.lower() == "no":
continue
if sel.isdigit():
index = int(sel)
if 1 <= index <= len(unique_folders):
folder = unique_folders[index - 1]
print("Opening:", folder)
open_folder(folder)
else:
print("Invalid number.")
continue
# ---- OPEN FILES ----
if choice == "2":
if not found_files:
print("No files available to open.")
continue
print("\n=== FILES ===")
for i, file in enumerate(found_files, 1):
print(f"{i}) 📄 {file}")
sel = input("\nChoose a file number (or 'no'): ").strip()
if sel.lower() == "no":
continue
if sel.isdigit():
index = int(sel)
if 1 <= index <= len(found_files):
file = found_files[index - 1]
print("Opening:", file)
open_file(file)
else:
print("Invalid number.")
continue
print("Invalid choice.")
Example Output
Choose search mode:
1) Search only in file/folder NAMES
2) Search also inside FILE CONTENTS
> 2
Searching...
📄 Found file: C:\Users\Example\Desktop\project.txt
📄 Found file: C:\Users\Example\Desktop\project.xlsx
📝 Found in content:C:\Users\Example\Desktop\MasterPlan.pptx
📁 Found folder: C:\Users\Example\Desktop\Project
Search completed in 5,237 seconds.
Would you like to open something?
1) Open a folder
2) Open to file
no) Continue to new search
> 2
=== FILES ===
1) 📄 C:\Users\Example\Desktop\project.txt
2) 📄 C:\Users\Example\Desktop\project.xlsx
3) 📄 C:\Users\Example\Desktop\MasterPlan.pptx
Choose a file number (or 'no'): 1
Opening: C:\Users\Example\Desktop\project.txt
🎉 What does the program do now?
✔ Search in file names
✔ Search in folder names
✔ Optional: Also search file contents
✔ Show separate lists:
📁 folders that match directly
🗂 folders that contain found files
✔ Avoid duplicates
✔ Maintains all folder opening functionality
✔ Avoid errors on binary or overly large files
Conclusion
Thanks to this new feature, the tool is now able to perform 360° searches — a bit like we would do with Windows, but much faster.
Happy searching 🔎!
Follow me #techelopment
Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment
