0

I'm pretty new to python, I'm using this as my second experience to continue my learning. My first project (using pandas for data analysis) will have been tougher than this one but this will be a new arena and I need some help to get started because I don't even know what to search for in any documentation.

I have many folders named for tv shows in one directory. And I have many files, of multiple episodes, of several of those shows, in another directory. An issue would be that each episode is stored into a folder of the same title when I download it. Until now I have been organizing the files manually but it's getting to where automating it would be nice (and a good learning exercise). Is there a way to search the 'Downloads' folder for folders that contain files that contain a string, say 'Homeland', and move that file (episode) into the folder titled "Homeland" that is in the other directory? I would also need to match more than one string per file/folder, like "Game" and "Thrones". Moving them to directories is easy enough, but getting the matching strings is where I'd love some insight. Then my next goal would be to loop over every file in 'Downloads' and sort it into the correct tv show's folder.

folders = 'list of folders in downloads'
#maybe I need to create a list here or a function that creates a list?

source_dir = "C:\Users\Downloads"
destination_dir = "C:\Users\TV Shows"
for folder_names in folders:
   if folder_name contains destination_name:
   # destination_name will be undefined but this is what i want
   source_path = str(source_dir) + str(file_name) + str(.mp4)
   destination_path = str(destination_dir) + str(file_name) + 
   str(.mp4)
      shutil.move(source_path, destination_path)
   if not:
      do nothing

It'll have to be changed because there are some variables that are going to yield errors and there's bad syntax but that's the general idea of what I want.

  • Have you looked at `pathlib`? Together with `shutil` you will write a simple script. See https://rednafi.github.io/digressions/python/2020/04/13/python-pathlib.html for a comprehensive use of pathlib – Prayson W. Daniel May 09 '20 at 05:27
  • Are you looking for a python-specific solution to this? If not, you could do this with a command from the shell: https://stackoverflow.com/a/22388517/10266625 – polortiz40 May 09 '20 at 05:29
  • `if "Game" in folder_name and "Thrones" in folder_name:` or even `if "game" in folder_name.lower() and "thrones" in folder_name.lower():` For more words you can use `for`-loop to check every word separatelly. – furas May 09 '20 at 07:11
  • BTW: `folders_and_files = os.listdir("downloads")` . OR with subfolders `for root, folders, files in os.walk("downloads"):` – furas May 09 '20 at 07:16
  • well I want to use python for some practice. Pathlib might work. I need my script to search a directory for folder names (I can get a list of folder names easily enough), then search another directory for all file names (can get list), and if there are at least two strings that match any files and any folders, then move that/those files into that folder. The issue lies in there being a lot of files and a lot of folders, so listing them out one by one isn't ideal. I need an "if two strings in filename match two strings in folder name then move file to folder" command. – Zachary Lane May 09 '20 at 08:00
  • so you have `if "Game" in folder_name and "Thrones" in folder_name:` - instead words `"Game"` `"Thrones"` you can use variabales with strings. And this way you can check any two words in folder name - `if word1 in folder_name and word2 in folder_name:` – furas May 09 '20 at 16:02
  • you can get filename, `split(' ')` to words and use `for`-loop to check every word separatelly in folder name and count words - if 2 or more words is in folder name then you can move it. – furas May 09 '20 at 16:09

1 Answers1

1

if you have many files and folders then use for-loops to work with them.

You will have to split filename to words - split(' ') - and use for-loop to check every word separatelly in folder name, and count words which are in folder name. When count is 2 or more then move file.

More or less:

all_filenames = [
    'Game of Throne part II.mp4',
    'other file.mp4',
]

all_folders = [
    'Game Throne',
    'Other Files'
]

for filename in all_filenames:

    words = filename.lower().split(' ')
    moved = False

    for folder in all_folders:

        count = 0

        for word in words:
            if word in folder.lower():
                count += 1

        if count >= 2:
            print('count:', count, '|', filename, '->', folder)
            # TODO: move file
            moved = True
            break

    if not moved:
        print('not found folder for:', filename)
        # TODO: you could move file to `Other Files`

EDIT: version which get all matching folders and ask user to choose correct folder.

I didn,t test it. It may need more code to check if user select correct number. And eventually add option to skip it and not move file.

all_filenames = [
    'Game of Throne part II.mp4',
    'other file.mp4',
]

all_folders = [
    'Game Throne',
    'Other Files'
]

for filename in all_filenames:

    words = filename.lower().split(' ')
    matching = []


    for folder in all_folders:

        count = 0

        for word in words:
            if word in folder.lower():
                count += 1

        if count >= 2:
            print('count:', count, '|', filename, '->', folder)
            matching.append(folder)

    #if not matching:
    if len(matching) == 0:
        print('not found folder for:', filename)
        # TODO: you could move file to `Other Files`
    elif len(matching) == 1:
        print('move:', filename, '->', matching[0])
        # TODO: move file to folder matching[0]
    else:
        for number, item in enumerate(matching):
            print(number, item)
        answer = int(input('choose number:'))
        print('move:', filename, '->', matching[answer])
        # TODO: move file to folder matching[answer]
furas
  • 134,197
  • 12
  • 106
  • 148
  • Thank you! Seems like this is just what I want. Is there a way to pass multiple delimiters into .split()? Would there also be a step to prompt it to ask me, if it found two folders that met the count>=2, which one I wanted to move it to? – Zachary Lane May 09 '20 at 21:07
  • with standard `split()` you can't use more delimiters but you can use module `re` (regular expressions). ie. `re.split('[., ]', 'a,b.c d')` gives `['a', 'b', 'c', 'd']` – furas May 10 '20 at 03:21
  • in current code it uses `break` to exit loop when it finds first folder matching words. You would have to do: before `for`-loop you would have to create empty list for matching folders, inside `if count >= 2:`you would have to add matching folder to list, and after `for`-loop you would have to use `len(list)` to check how many matching folders you found. And if you get 2 or more then you can print then and use `input()` for user's decision. – furas May 10 '20 at 03:24
  • Furas, this is the template for my code so thank you so much. There is one issue I can't think of how to resolve: count +=1 is adding every word that matches, which is good but it is also adding duplicate words. Is there a way I can tell it to ignore duplicate words? – Zachary Lane May 11 '20 at 23:58
  • use `set()` to get only unique words `len( set(["word", "word"]) )` gives `1` so you could use `words = set(words)` or `words = list( set(words) )` – furas May 12 '20 at 00:01
  • New problem. For every action I tell it to do under 'if not count >= 2:', it loops that endlessly, so it seems (I haven't tried to go through each loop). I'm prompting it to 'if not count >= 2' to move it to another folder via the input function (if yes move here if no then pass), but it appears to loop that request. – Zachary Lane May 12 '20 at 04:18
  • instead of `if not count >= 2` you could write `'if count < 2'` - is this what you expected ? If you have problem then use `print()` to see values in variables and which part of code is executed - ie. `print(count, not count >= 2 )` - it helps to see where can be problem and you don't have to learn how to use debuger. BTW: if this not help then create new question on new page - you will have more space to put full code, new people will see your problem and they can show new solutions. – furas May 12 '20 at 04:24
  • Yea I tried printing things along the way. With if not and if count < 2 it loops through all the if not/if < 2 operations. Thanks for your help. I'll go it alone from here. But this was very helpful to get me started. Thank you. – Zachary Lane May 12 '20 at 06:23