Last active
January 17, 2023 15:43
-
-
Save nutrino/95fa1cf2e74574818fe9722a6086058b to your computer and use it in GitHub Desktop.
set image file date from exif data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# https://gist.github.com/ikoblik/7089165 | |
"""A simple utility to restore file creation and modification | |
dates back to their original values from EXIF. | |
This script requires exif module to be installed or the exif | |
command line utility to be in the path. | |
To function correctly under windows this script needs win32file and | |
win32con modules. Otherwise it will not be able to restore the creation | |
date.""" | |
import os, sys, time, re, glob | |
import os.path | |
from datetime import datetime, timedelta | |
from PIL import Image | |
from PIL.ExifTags import TAGS | |
TEN_MINUTES = timedelta(minutes=10) | |
__description = """Restores file's creation and modification dates back to the original | |
value from EXIF. | |
usage: exif_date.py [File name mask]""" | |
def get_exif_timestamp(src) : | |
ret = {} | |
exifTimestamp = '' | |
i = Image.open(src) | |
try : | |
info = i._getexif() | |
if info is None: | |
import re | |
m = re.search(r'(\d{4})(\d{2})(\d{2})(?:-|_)(\d{2})(\d{2})(\d{2})', src) | |
if m is not None and len(m.groups()) == 6: | |
return '{}:{}:{} {}:{}:{}'.format(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5),m.group(6)) | |
m = re.search(r'(\d{4})-(\d{2})-(\d{2}) (\d{2})\.(\d{2})\.(\d{2})', src) | |
if m is not None and len(m.groups()) == 6: | |
return '{}:{}:{} {}:{}:{}'.format(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5),m.group(6)) | |
for tag, value in info.items() : | |
decoded = TAGS.get(tag, tag) | |
ret[decoded] = value | |
if ret.get('DateTimeOriginal') != None : | |
return ret['DateTimeOriginal'] | |
if ret.get('DateTimeDigitized') != None: | |
return ret['DateTimeDigitized'] | |
if ret.get('DateTime') != None: | |
return ret['DateTime'] | |
except Exception as e : | |
print(e) | |
return exifTimestamp | |
def getFileDates(path): | |
"""Returns a dictionary of file creation (ctime), modification (mtime), exif (exif) dates""" | |
dates = {} | |
exif_timestamp = get_exif_timestamp(path) | |
if exif_timestamp != '': | |
dates['exif'] = datetime.strptime(exif_timestamp, '%Y:%m:%d %H:%M:%S') | |
else: | |
dates['exif'] = None | |
dates['mtime'] = datetime.utcfromtimestamp(os.path.getmtime(path)) | |
dates['ctime'] = datetime.utcfromtimestamp(os.path.getctime(path)) | |
return dates | |
def setFileDates(fileName, dates): | |
"""Sets file modification and creation dates to the specified value""" | |
os.utime(fileName, (time.mktime(dates['exif'].utctimetuple()),)*2) | |
def fixFileDate(fileName): | |
"""Reads file's EXIF header, gets the earliest date and sets it to the file""" | |
dates = getFileDates(fileName) | |
if (dates['exif']): | |
cmp_time = lambda x, y: x - y > TEN_MINUTES | |
diff = [cmp_time(dates[x], dates['exif']) for x in ('mtime', 'ctime')] | |
if(sum(diff)): | |
setFileDates(fileName, dates) | |
return dates, diff | |
else: | |
return dates, None | |
def main(args): | |
if (not len(args)): | |
return - 1 | |
processedFiles = [] | |
for fileNameMask in args: | |
if "*" in fileNameMask or "?" in fileNameMask: | |
print("Looking for files with mask " + fileNameMask) | |
for fileName in filter(lambda x: x not in processedFiles, glob.glob(fileNameMask)): | |
processedFiles.append(fileName) | |
print(fileName + ' - ') | |
try: | |
dates, diff = fixFileDate(fileName) | |
except Exception as e: | |
print(e) | |
diff = None | |
if (not diff): | |
print('SKIP, NO EXIF') | |
else: | |
if (sum(diff) != 0): | |
print('SET TO "%s" (updated M:%d, C:%d)' % (dates['exif'].strftime('%Y:%m:%d %H:%M:%S'), diff[0], diff[1])) | |
else: | |
print('OK') | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv[1:])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment