#!/bin/env python3 # vim: set noexpandtab tabstop=4 ft=python : """ A script moving pictures from one folder to subfolders (depending on the date they are taken) """ import os import argparse import re import shutil import PIL.Image import PIL.ExifTags def get_date(filename): """ Read EXIF data from a file and return a string containing "yyyymmdd" :param filename: The files name """ image = PIL.Image.open(filename) image_exif = image._getexif() if not image_exif: return None matches = re.match(r'(?P\d{4}):(?P\d{2}):(?P\d{2})', image_exif[306]) image.close() if matches is None: return None return "%04d%02d%02d" % (int(matches["year"]), int(matches["month"]), int(matches["day"])) def create_directory(directory): """ Try to create the directory return False when there’s already something there that’s not a directory """ if os.path.exists(directory): if not os.path.isdir(directory): print("'%s' exists but is no directory!" % (directory)) return False else: print("Creating directory '%s'" % (directory)) os.mkdir(directory) return True def main(): """ Move files to a directory by date :param args: CLI arguments """ # verify we're getting the correct data :) if PIL.ExifTags.TAGS[306] != "DateTime": print("ERROR: EXIF index for DateTime changed!") exit(2) # parse arguments parser = argparse.ArgumentParser(description="Move/copy pictures to subfolders") parser.add_argument("--source", "-s", action="store", default=os.getcwd(), metavar="", \ help="The source directory (default = current)", dest="source") parser.add_argument("--destination", "-d", action="store", default=os.getcwd(), metavar="", \ help="The destination directory (default = current)", dest="destination") parser.add_argument("--copy", "-c", action="store_true", dest="copy_files", \ help="Copy the files insted of moving them") parser.add_argument("--existing", "-e", action="store", dest="existing_files", \ choises=["ask", "skip", "overwrite"], default="ask", \ help="What to do with existing files") args = parser.parse_args() # settings source_directory = args.source destination_directory = args.destination copy_files = args.copy_files existing_files = args.existing_files # iterate through directory for filename in os.listdir(source_directory): if os.path.isfile(os.path.join(source_directory, filename)) and \ re.search(r'\.jpg$', filename, flags=re.IGNORECASE): date = get_date(os.path.join(source_directory, filename)) if date is None: print("WARNING: No EXIF data for file '%s'" % (filename)) continue directory = os.path.join(destination_directory, date) # create directory if it not exists if not create_directory(directory): continue # copy or move file write_file = True if os.path.exists(os.path.join(destination_directory, date, filename)) and \ existing_files != "overwrite": write_file = False if existing_files == "ask": overwrite = input("File '%s' exists! Overwrite? [yn]: ") while overwrite not in ["y", "n"]: overwrite = input("File '%s' exists! Overwrite? [yn]: ") write_file = overwrite == "y" if not write_file: print("Skipping file '%s'" % (filename)) elif copy_files: print("Copy file '%s' to '%s'" % (filename, date)) shutil.copy2(os.path.join(source_directory, filename), \ os.path.join(destination_directory, date, filename)) else: print("Moving file '%s' to '%s'" % (filename, date)) os.rename(os.path.join(source_directory, filename), \ os.path.join(destination_directory, date, filename)) if __name__ == "__main__": main()