Skip to content

Instantly share code, notes, and snippets.

@avdyushin
Last active June 20, 2018 19:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avdyushin/e6068aa152bb7a51187026da0a9adb0c to your computer and use it in GitHub Desktop.
Save avdyushin/e6068aa152bb7a51187026da0a9adb0c to your computer and use it in GitHub Desktop.
Reorder photos by Exif date
#!/usr/bin/python
# coding: utf8
import io
import re
import time
import shutil
import os.path
import hashlib
import argparse
import mimetypes
import exifread
from datetime import datetime
class PreparePhotos:
def __init__(self, target_folder = ".", destination_folder = "./output"):
self.target_folder = target_folder
self.destination_folder = destination_folder
def sync(self, args):
for directory, _, files in os.walk(self.target_folder):
for filename in files:
path = os.path.join(directory, filename)
mimetype, _ = mimetypes.guess_type(path)
name, ext = os.path.splitext(path)
if (mimetype and mimetype.startswith('image/')) or ext.upper() == '.HEIC':
tags = exifread.process_file(open(path, 'rb'), details=False)
self.move(path, tags)
print 'Done'
def md5(self, path):
hash_md5 = hashlib.md5()
with open(path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def move(self, path, tags):
date = None
if 'EXIF DateTimeOriginal' in tags.keys():
# 2013:06:01 18:26:49
date = str(tags['EXIF DateTimeOriginal'])
try:
date = datetime.strptime(date, '%Y:%m:%d %H:%M:%S')
except ValueError:
date = datetime.fromtimestamp(os.stat(path).st_birthtime)
else:
date = datetime.fromtimestamp(os.stat(path).st_birthtime)
model = ''
if 'Image Model' in tags.keys():
model = '_' + str(tags['Image Model']).replace(' ', '_')
filename, ext = os.path.splitext(path)
yearstr = date.strftime('%Y')
datestr = date.strftime('%Y-%m-%d')
source_dir = os.path.join(self.destination_folder, yearstr, datestr)
print 'Moving', path, '...'
if not os.path.isdir(source_dir):
print 'Creating', source_dir, '...'
os.makedirs(source_dir)
source_name = date.strftime('%Y%m%d-%H%M%S') + model
source_fullpath = os.path.join(source_dir, source_name + ext)
if os.path.exists(source_fullpath):
if self.md5(path) == self.md5(source_fullpath):
print 'Skipping', source_fullpath, '...'
return source_fullpath
postfix = 1
while True:
new_fullpath = os.path.join(source_dir, source_name + '-' + str(postfix) + ext)
if os.path.exists(new_fullpath) and self.md5(path) == self.md5(new_fullpath):
print 'Skipping', new_fullpath, '...'
return new_fullpath
if not os.path.exists(new_fullpath):
source_fullpath = new_fullpath
break
postfix += 1
utime = time.mktime(date.timetuple())
shutil.copy(path, source_fullpath)
os.utime(source_fullpath, (utime, utime))
print '->', source_fullpath
return source_fullpath
parser = argparse.ArgumentParser(description="Foo")
parser.add_argument("--quite", help="quite")
parser.add_argument("target_folder", help="target folder")
parser.add_argument("destination_folder", help="destination folder")
args = parser.parse_args()
tf = args.target_folder
df = args.destination_folder
#tf = "photos"
#df = "output"
pp = PreparePhotos(target_folder = tf, destination_folder = df)
pp.sync(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment