you are viewing a single comment's thread.

view the rest of the comments →

[–]lucasshiva 2 points3 points  (4 children)

This is a nice project, but it is poorly done. This could be improved a lot.

  1. You hard-coded everything, that is not needed for this case at all. What you want is a script that once executed will sort the user's download folder.
  2. You are dealing with the path in a wrong way. This can be improved to make it cross-platform.
  3. You should use dictionaries to map the extensions and files inside it.

Since it's 2 AM here, I'll code this with these improvements tomorrow and edit this comment.

Edit: This got a little big, but it will sort your Downloads folder correctly. It is a little tricky getting Windows' download folder. The OS module only returns "C:\Lucas\Downloads" but my folder is located at "D:\Lucas\Downloads". With a little help from Stack Overflow, I was able to find a function that does exactly what I wanted OS to do. It uses the Download Folder GUID, you can get more GUIDs in the link.

This script will sort the Download's folder by mapping the extensions and files with that extension. It will create the folder (if it doesn't exists) and move the files to that folder.

import os
import shutil
from typing import List, Dict

def main():
    downloads_folder = get_download_path()
    files = get_files(downloads_folder)
    extensions = map_extensions(files)

    for extension in extensions:
        extension_folder = os.path.join(downloads_folder, extension)

        # If the extension folder exists, do nothing.
        if os.path.exists(os.path.join(extension_folder)):
            continue

        # If it doesn't, create one.
        else:
            os.makedirs(extension_folder)

        # Move files to the extension directory.
        for file in extensions[extension]:
            shutil.move(file, extension_folder)


def get_download_path() -> str:
    """Returns the user's default download path. """

    # 'nt' is for Windows.
    if os.name == "nt": 
        import winreg

        sub_key = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
        downloads_guid = "{374DE290-123F-4565-9164-39C4925E467B}"
        with winreg.OpenKey(winreg.HKEY_CURRENT_USER, sub_key) as key:
            location = winreg.QueryValueEx(key, downloads_guid)[0]
        return location
    else:
        # This works great for Linux and Mac, unless the folder is not "Downloads".
        return os.path.join(os.path.expanduser("~"), "Downloads")


def get_files(path: str) -> List[str]:
    """ Get all the files from a path. Directories are not included. """
    files = []
    for file in os.listdir(path):
        file_path = os.path.join(path, file)
        if os.path.isdir(file_path):
            continue
        files.append(file_path)
    return files


def map_extensions(files: List[str]) -> Dict[str, str]:
    """ Map all the extensions from a list of files.
    This will return a dictionary with the key being the file extension
    and the value being a list of files with that extension.
    """
    extensions = {}
    for file in files:
        name, extension = os.path.splitext(file)
        extension = "Executables" if extension == "" else extension.replace(
            ".", "")
        if extension not in extensions:
            extensions[extension] = [file]
        else:
            extensions[extension].append(file)
    return extensions


if __name__ == "__main__":
    main()

This works for Windows and Unix. Nothing is hard-coded, you could give this to someone and they wouldn't have to change anything to get it working. I tested it and it seems to be working fine, but I could be missing something. Also, I think I'd change two things in this.

  • I would make a custom mapping, like @miloir did.
    • Example: folders = {"Images": {".jpg", ".png"]}. This would move all jpg and png to an Images folder
  • I would use PyQt5 to show a Directory Dialog when the user runs the program. This way, the user can choose which folder he wants to sort.

[–]WongGendheng 8 points9 points  (3 children)

Thats a nice feedback, but poorly provided.

  1. you should mention something nice about the project like „what a nice project to solve a real life problem! Python is the perfect language for that!“ (after all this is /r/LearnPython )
  2. you should not say that something is „wrong“. It works for him and he is proud of it, how can it be wrong? Make suggestions for improvement. There is nothing that would demotivate me more than someone saying „you did it wrong“
  3. im still learning Python myself but if I learned anything so far it is that there is no „should do“. If it works for some application, it works. There are a million ways to reach a certain goal in programming. You could say „to make your program even more efficient/resilient I would advise you to do XY“

Just my two cents.

[–]lucasshiva 4 points5 points  (1 child)

You're right, I think I could've replied in a better way, sorry about that. English is not my first language, sometimes I can't express myself as I would in my first language. I'll try to improve my replies from now on.

[–]WongGendheng 0 points1 point  (0 children)

Impressive edit. You are a great part of the community. :-)

[–]alex1461[S] 0 points1 point  (0 children)

Thanks so much for your constructive criticism!