3
\$\begingroup\$

I have a huge Google Photos directory that is difficult to navigate - there are just too many files so I thougt I need to sort them somehow. I decided to make it simple and group them by date-taken. As I always wanted to learn python I thought I'll give it a try so this is my first take on it.

There is no rocket-science here (yet). It looks for files in the pictures_path, groups them by their modified date, enumerates this iterator, creates directories and moves or copies files according to the whatif option. This is measured by the perf_counter().

I'd be great if you could take a look at it and tell me whether I did something terribly wrong as a beginner before I let it work with my actual collection.

import os
import time
import itertools
import shutil
from pprint import pprint

def format_filemtime(path):
    filemtime = os.path.getmtime(path)
    return time.strftime('%Y-%m-%d', time.gmtime(filemtime))

def group_pictures(whatif=False):
    pictures_path = "C:\\temp\\picturepy\\pictures\\"
    galleries_path = "C:\\temp\\picturepy\\galleries\\"

    start = time.perf_counter()

    picture_names = os.listdir(pictures_path)

    print(f"picture count: {len(picture_names)}")

    pictures_by_mtime = itertools.groupby(picture_names, lambda name: format_filemtime(os.path.join(pictures_path,name)))

    for (dir, picture_names) in pictures_by_mtime:
        path_dir = os.path.join(galleries_path, dir)
        if not os.path.exists(path_dir):
            os.makedirs(path_dir)
            print(f"'{dir}' created.")
        else:
            print(f"'{dir}' already exists.")

        do = shutil.copyfile if whatif else shutil.move
        verb = "copied" if whatif else "moved"

        for file in picture_names:
            do(
                src=os.path.join(pictures_path, file), 
                dst=os.path.join(path_dir, file))                
            print(f"\t'{file}' {verb}.")

    end = time.perf_counter()
    elapsed = round(end - start,2)
    print(f"elapsed: {elapsed} sec")

# --- --- ---

def main():
    group_pictures(whatif=True)
    #group_pictures()

if __name__ == '__main__':
    main()

I tested it with VSCode and it's doing its job pretty well.

\$\endgroup\$
2
\$\begingroup\$

This looks pretty decent for a first Python program, so good job on that.

I only have a few small nitpicks

  • Some PEP8 violations, but nothing major

    1. There should be a <space> after the ,

    2. Line too long (max 79)

  • Consider making the directory paths global constants

    PEP8 reference

    PICTURES_PATH = "C:\\temp\\picturepy\\pictures\\"
    GALLERIES_PATH = "C:\\temp\\picturepy\\galleries\\"
    
  • I think whatif could have a better name

    What if what? It's not really clear what this variable is supposed to do

    Maybe rename it to keep_original, because the copy will leave the original intact

  • Possible to do the if else in one line with unpacking

    do = shutil.copyfile if whatif else shutil.move
    verb = "copied" if whatif else "moved"
    

    Would become

    do, verb = (shutil.copyfile, "copied") if keep_original else (shutil.move, "moved")
    
\$\endgroup\$
  • 1
    \$\begingroup\$ Cool! I can explain the weird whatif - my first try was with powershell (but I gave up) and its commandlets use this kind of switch so I followed this bad example but you're right about everything and also keep_original is much better :) \$\endgroup\$ – t3chb0t Oct 24 '18 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.