How to group files with the same prefix but different extensions into folders using Python

After, for example, re-encoding your videos, you often have a bunch of files in the same directory named e.g. MyMovie.avi and MyMovie.avi.mkv.

The following script will sort all files with the same prefix (MyMovie) into a directory called like the prefix. This allows easy sorting and comparing of those files.

Other files will not be touched. The operation is performed non-recursively and no files will be overwritten.

Note that the list of file extensions is hardcoded and double extensions such as .avi.mkv are also treated like standard extensions. The extension check is performed using .endswith()

#!/usr/bin/env python3
import argparse
import os
from collections import defaultdict

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("directory", help="path to the directory")
    args = parser.parse_args()

    directory = args.directory

    extensions = [
        ".avi",
        ".mkv",
        ".mp4"
    ]

    # Add extensions such as ".avi.mp4" at the front
    # so we check them first
    extensions = [e1 + e2 for e1 in extensions for e2 in extensions] + extensions

    files_by_prefix = defaultdict(list)
    for file in os.listdir(directory):
        # Split extension
        for potential_extension in extensions:
            if file.endswith(potential_extension):
                file_prefix = file[:-len(potential_extension)]
                files_by_prefix[file_prefix].append(file)

    # Ignore prefixes with only one file
    files_by_prefix = {k: v for k, v in files_by_prefix.items() if len(v) > 1}

    # Create directory for every prefix and move all the files into it
    for prefix, files in files_by_prefix.items():
        os.makedirs(os.path.join(directory, prefix), exist_ok=True)
        # Move file using if destination doesn't exist
        for file in files:
            print(f"{file} -> {prefix}/{file}")
            os.rename(os.path.join(directory, file), os.path.join(directory, prefix, file))