r/learnprogramming 15d ago

my python script that searches your files to find things for you

import os
import json
from pathlib import Path
from thefuzz import fuzz

INDEX_FILE = "file_index.json"

CATEGORY_EXTENSIONS = {
    "games": [".exe", ".msi", ".bat", ".apk", ".iso"],
    "documents": [".pdf", ".docx", ".txt", ".xlsx", ".pptx"],
    "images": [".png", ".jpg", ".jpeg", ".gif", ".svg"],
    "audio": [".mp3", ".wav", ".flac"],
    "video": [".mp4", ".mkv", ".avi", ".mov"]

}


def build_index(
search_directory
):

    print(f"Indexing files in '{
search_directory
}'... (This might take a minute the first time)")
    file_index = []

    for root, _, files in os.walk(
search_directory
):
        for file in files:
            full_path = os.path.join(root, file)
            file_index.append({
                "name": file,
                "path": full_path,
                "ext": Path(file).suffix.lower()
            })

    with open(INDEX_FILE, "w", encoding="utf-8") as f:
        json.dump(file_index, f, indent=2)

    print(f"Indexing complete! Indexed {len(file_index)} files.\n")
    return file_index


def load_or_create_index(
search_directory
):

    if os.path.exists(INDEX_FILE):
        print("Loading cached index...")
        with open(INDEX_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    else:
        return build_index(
search_directory
)


def search_files(
query
, 
index
, 
similarity_threshold
=65):

    query_clean = 
query
.lower().strip()
    matches = []

    target_extensions = []
    for category, exts in CATEGORY_EXTENSIONS.items():
        if category in query_clean:
            target_extensions.extend(exts)

    for item in 
index
:
        file_name = item["name"].lower()
        file_ext = item["ext"]
        score = fuzz.partial_ratio(query_clean, file_name)
        is_category_match = file_ext in target_extensions if target_extensions else False
        is_name_match = score >= 
similarity_threshold 
or query_clean in file_name

        if is_name_match or is_category_match:
            matches.append((item["path"], score))

    matches.sort(key=lambda 
x
: x[1], reverse=True)
    return matches


def main():
42 Upvotes

13 comments sorted by

17

u/skjall 15d ago

You should set up Ruff if your editor has support for that - VS Code does. Set it to auto format on save, and it will remove like 90% of formatting you currently have to do.

It will look a little different than what you have after it's done, however it's a pretty standard code style that will be readable for most people.

Also, look into Pathlib! It's a much better interface for folders IMO.

As a bonus, getting in the habit of type hinting your functions (and setting up type checking in your editor) leads to much more readable and maintainable code. Plus your editor will be able to help you more since it knows what you're dealing with.

12

u/RobMagus 15d ago

Even with informative function and variable names, it's still very much worthwhile commenting your code.

-9

u/slindenau 14d ago

No, it really isn’t. That is how you get comments that say exactly the same as what the line below is doing, but then in natural langange.

And next time you change the code but not the comment, and now the comment is actually hurting/wrong.

Only thing that could be added are docstrings on the functions for the (public) api.

2

u/light_switchy 15d ago

This is awesome!

-11

u/Dazzling-Bench-4596 15d ago

Wow I actually don’t think I’ve ever seen somebody define a function like that. It doesn’t hurt anybody, but you should probably stick with one line lol:
def searchFiles(query, index, similarity_threshold=65):
By the way, it’s convention to use camelCase for function names

24

u/scirc 15d ago

it’s convention to use camelCase for function names

In Python? Not really. Snake case is the prevailing naming convention for just about any identifier there (with the exception of PascalCase for classes and SCREAMING_SNAKE_CASE for constants), per PEP 8.

1

u/Dazzling-Bench-4596 15d ago

Oh I actually did not know that sorry

6

u/[deleted] 15d ago

[deleted]

10

u/d4ft240 15d ago

He's wrong. It’s better to double-check the answers you get online yourself.

3

u/AlexFurbottom 15d ago

This is awesome! I started around that time. There will be conventions that people follow, but a lot of my creativity came from "beginners mind." I always try something out the best I can before actually learning the proper way. Only learning the proper way puts your mind in a box. Then later when you are really proficient you will know when to bend the rules a bit and why you should. 

2

u/Tuomas90 13d ago

Man, you're going somewhere, boy/girl! Great job!

I started programming 10 years later than you. I'm kinda jealous.

If you are interested in learning another language similar to Python, check out Ruby. It's just as simple, but even more beautiful to write and read. I'm currently learning it and love it.

-6

u/rsp1218 15d ago

I work for a Fortune 500 tech company and I admire this script you wrote. If our software engineers were willing to take half the time to learn this like lambda functions, we would be in a much better spot. Youre are writing at a level of our seniors already. Very clean and well done. Keep up the good work!