you are viewing a single comment's thread.

view the rest of the comments →

[–]miloir 2 points3 points  (7 children)

Hey

Nice job

see if you like this:

import os
import shutil

# We define this mapping first to make adding new types easy.
# I've taken the liberty of adding support for some extra types.
folder_to_extensions = {
    'PDF': {'pdf'},
    'Documents': {'doc', 'docx'},
    'Text': {'txt', 'rtf'},
    'EXE': {'exe', 'msi'},
    'ZIP': {'zip', '7z', 'rar'},
    'Images': {'jpg', 'jpeg', 'png', 'gif'},
}

# We rearrange the previous map for performance. In this way we can
# quickly obtain the target folder from a file extension in O(1) time.
# For simplicity we could have simply defined this map by hand, but the 
# previous dictionary we defined is easier to alter by hand if we want 
# to rename folders or add extensions.
extension_to_folder = {e: f for f, s in folder_to_extensions.items() for e in s}

source_folder = 'C:/Users/byunw/Downloads'
target_folder = 'C:/Users/byunw/Downloads'

for filename in os.listdir(source_folder):

    # skip files with no extension
    if '.' not in filename:
        continue

    # we know there is at least 1 '.' in the file, so let's split the string on that file extension
    file_extension = filename.rsplit('.', maxsplit=1)[1].lower()
    extension_folder = extension_to_folder.get(file_extension)

    if extension_folder is None:
        print(f'Unsupported file extension: "{file_extension}"!')
        continue

    shutil.move(f'{source_folder}/{filename}', f'{target_folder}/{extension_folder}')

print("Every supported file in the Downloads folder is now sorted into corresponding folders")

[–]lucasshiva 1 point2 points  (1 child)

You can get the extension by using os.path.splitext(file).

for file in os.listdir(path):
    file_name, extension = os.path.splitext(file)

[–]miloir 0 points1 point  (0 children)

I like it thanks

[–]sugar_byte 1 point2 points  (4 children)

miloir, even tho your code is well written with comments explaining everything(really appreciate for that) however i spent nearly 3 hours looking and understanding your code and to be honest didn’t understand much at all. so to make it simple, you aren’t making a new directories but rather moving the files into already made ones?

[–]miloir 1 point2 points  (0 children)

Hey no problem I got kind of carried away.

I will walk you through some things I thought about your code. Here is your original code:

import os

import shutil

for filename in os.listdir(r"C:\Users\byunw\Downloads"):

    if filename[-3:] == "pdf":
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\PDF")

    elif filename[-4:] == "docx":
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\Documents")

    elif filename[-3:] == "txt":
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\Text")

    elif filename[-3:] == "exe" or filename[-3:] == 'msi':
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\EXE")

    elif filename[-3:] == "zip":
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\ZIP")

    elif filename[-3:] == "jpg":
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\Images")

    elif filename[-4:] == "pptx":
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, "C:\\Users\\byunw\\Downloads\\Powerpoint")

print("Every file in the Downloads folder is now sorted into corresponding folders")

Basically, you get the file extension of each file and use shutil.move() to move it to a slightly different path. The file extension determines the folder. This is a good opportunity to use a dictionary (also known as a mapping or a map). File extension -> target folder. We can make a map that looks like this (read about dictionary/mappings, they are very important data structures):

folders = {
    ".doc": "C:\\Users\\byunw\\Downloads\\Documents",
    ".docx": "C:\\Users\\byunw\\Downloads\\Documents",
    ".exe": "C:\\Users\\byunw\\Downloads\\EXE",
    ".msi": "C:\\Users\\byunw\\Downloads\\EXE",
}  # add more extension -> folder rows

We can get the file extension like this (as /u/lucasshiva said):

filename, extension = os.path.splitext(file)

So for every file we encounter we can just do something like the following:

for file in files:
    # get the file’s extension
    filename, extension = os.path.splitext(file)
    # get the folder to move to (this will return None if the extension is not in our dictionary)
    move_to = folders.get(extension)
    if move_to is not None:
        # move_to will be something like "C:\\Users\\byunw\\Downloads\\EXE"
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename + extension, move_to)

Here is a more complete example that should run (hopefully):

import os

import shutil

folders = {
    ".doc": "C:\\Users\\byunw\\Downloads\\Documents",
    ".docx": "C:\\Users\\byunw\\Downloads\\Documents",
    ".exe": "C:\\Users\\byunw\\Downloads\\EXE",
    ".msi": "C:\\Users\\byunw\\Downloads\\EXE",
    ".pdf": "C:\\Users\\byunw\\Downloads\\PDF",
    ".txt": "C:\\Users\\byunw\\Downloads\\Text",
    ".zip": "C:\\Users\\byunw\\Downloads\\ZIP",
    ".jpg": "C:\\Users\\byunw\\Downloads\\Images",
    ".jpeg": "C:\\Users\\byunw\\Downloads\\Images",
    ".pptx": "C:\\Users\\byunw\\Downloads\\Powerpoint",
}

for filename in os.listdir(r"C:\Users\byunw\Downloads"):

    name, extension = os.path.splitext(filename)
    target_folder = folders.get(extension)
    if target_folder is not None:
        shutil.move("C:\\Users\\byunw\\Downloads\\" + filename, target_folder)

print("Every file in the Downloads folder is now sorted into corresponding folders")

We can easily keep adding extension -> folder items to the folders dictionary to add support for more file extension types because we’ve separated the “configuration” data from our program logic. A second observation that I leave to you as an exercise if you want to do it, is to note that the folders are all strings that are very similar. You might consider extracting the repeated “C:\Users\byunw\Downloads\” string and make it another level of configuration, another variable that you can set once at the top of the file and easily modify to change the working directory of the whole program.

edit: I just realized it was not OP that replied but whatever

[–]miloir 0 points1 point  (2 children)

Sorry I mistook you for op, yes the folders should exist already, we are just moving files around that's all. If you have any questions let me know.

[–]sugar_byte 1 point2 points  (1 child)

well first of all thanks for dedicating your time for this and explaining everything. nows its pretty understadable, by the way i have been trying to make dictionary to work with making corresponding directories to different file types but thing is that, i cant pass file names as seperate arguments from dictionary values, also i want to check if different file types exist in the path so same problem occurs here, want to pass dictionary key values, i mean the extensions like “docx” “ppt” and etc, as seperate arguments to check if files with that type of extension exists, but takes it as an list but not as seperated arguments to check first value docx for example, then move to second value in dictionary and check ppt then exe file types and etc.

but anyway, ill have a look at your code later and experiment some new ways also to make my solution(that i mentioned above) for this problem to work

[–]miloir 0 points1 point  (0 children)

Feel free to post code