Here's what I came up with:
# rename_media_by_age()
#
# automatically rename pictures and videos to start with age
# from specified date. Written for baby pictures.
# Example: Changes name from 'foo' to '##Y##M##D_foo'
# ie - 'foo.jpg' to '01Y03M10D_foo.jpg' if pic taken 1 year, 3 months, 10
# days after birth
#
# I tried to keep it simple, so I just copy it into a folder with files I
# want to rename and then run it
# I put all video files in a subfolder called 'videos'
# change variable folder_videos below if you do something different
#
# my files came from many different sources
# (iPhone, android phone, multiple cameras, ipcamera)
# and they don't all have the same info, so here's what I came up with
#
# for *.jpg pictures:
# - try to read exif info
# - if that doesn't work, I use FileModDate
#
# for videos:
# mp4 files from android phone
# -named as VID_YYYYMMDD_HHMMSS.mp4
# -I use picasa, which doesn't like mp4 files, so I rename as .mov
# -then just use the date from the original filename
# mov files from iphone & camera
# - use file modification date
#
# exif code stolen from here:
# http://code.activestate.com/recipes/578672-sort-images-from-different-sources-by-picture-take/
#
#
# v1 - Nathan Tomlin. Feb 12, 2012. nathan.a.tomlin@gmail.com
# v2 - Feb 28, 2012. Fixed error in .jpg renaming and added .wmv check
# v3 - Aug 11, 2013. Fixed error in age rename and added .mp4 check
# v4 - Apr 5, 2014. Convert from matlab to python, remove .3gp & .wmv code
#
import os
import glob
import re
from PIL import Image
from datetime import datetime
from math import floor
dtime0 = datetime(2010,1,1,8,23,00) # birthday - basis of file renames
# format (YYYY,MM,DD,HH,MM,SS)
regexp_str = '\d\dY\d\dM\d\dD_' # this is the regexp used to match names
# current looking for '##Y##M##D_*' where # = number
#folder_pics = os.getcwd()
folder_videos = 'videos' # just set as empty string ('') if videos in same directory as pictures
# this defaults to look for 'videos' folder in start folder
def check_filename(filename):
# check whether file already has correct name
imatch = re.search(regexp_str,filename)
return imatch
def get_image_creation_datetime(filename):
### exif code stolen from here:
### http://code.activestate.com/recipes/578672-sort-images-from-different-sources-by-picture-take/
try:
img = Image.open(filename)
except (Exception) as e:
print('Image.open failed on',filename, "due to", e)
#mtime = "?"
else:
# read exif data and set mtime to be earliest datatime found
exif_data = img._getexif()
mtime = "?"
if 306 in exif_data and exif_data[306] < mtime: # 306 = DateTime
mtime = exif_data[306]
if 36867 in exif_data and exif_data[36867] < mtime: # 36867 = DateTimeOriginal
mtime = exif_data[36867]
if 36868 in exif_data and exif_data[36868] < mtime: # 36868 = DateTimeDigitized
mtime = exif_data[36868]
if mtime != "?": # got a valid datetime from exif data
dtime = datetime.strptime(mtime, "%Y:%m:%d %H:%M:%S")
else: # no exif data - use file modification time instead
print(filename, "could not find exif creation time!")
dtime = get_file_mod_datetime(filename)
return dtime
def get_file_mod_datetime(filename):
#t = os.path.getctime(filename)
#print(datetime.fromtimestamp(t))
t = os.path.getmtime(filename)
dtime = datetime.fromtimestamp(t)
return dtime
def date2agestr(dtime):
# convert from datetime to agestr ##Y##M##D_ format
d = dtime - dtime0
days = d.days
Ydays = 365.25 # average days/year
Mdays = Ydays/12 # average 30.4375 days/month...
Y = floor(days/Ydays)
M = floor((days - Y*Ydays)/Mdays)
D = round(days - Y*Ydays - M*Mdays)
agestr = str(Y).zfill(2) + 'Y' + str(M).zfill(2) + 'M' + str(D).zfill(2) + 'D_'
return agestr
def rename(name_old,agestr,ext=''):
# rename file with new name: append agestr to old name
# change file extension if input ext
name_new = agestr + name_old
name_base = name_new[:-4]
if ext == '':
name_ext = name_new[-4:]
else:
name_ext = ext
name_new = name_base + name_ext
# check whether name already exists
if os.path.isfile(name_new):
k=0
while os.path.isfile(name_new):
name_new = name_base + '_' + str(k) + name_ext
k+=1
try:
os.rename(name_old,name_new)
#print(name_old,name_new)
except (Exception) as e:
print('os.rename failed for',name_old,'to',name_new,'due to',e)
return name_new
if __name__=="__main__":
# jpg files
ext = '.jpg'
files = glob.glob('*'+ext)
k = 0;
for file in files:
# check whether file already has correct name
imatch = check_filename(file)
#filename = files[m]
if imatch == None: # file did not match, need to fix name
dtime = get_image_creation_datetime(file) # datetime from exif
agestr = date2agestr(dtime) # generate age string ('##Y##M##D_')
rename(file,agestr) # rename
k+=1
print('renamed',str(k),ext,'files')
# change to video directory
os.chdir(folder_videos)
# .mov videos from iphone & camera in form MVI_####.mov or IMG_####.mov
# use file modification date for datetime
ext = '.mov'
files = glob.glob('*'+ext)
k = 0;
for file in files:
# check whether file already has correct name
imatch = check_filename(file)
if imatch == None: # file did not match, need to fix name
dtime = get_file_mod_datetime(file) # datetime from file mod
agestr = date2agestr(dtime) # generate age string ('##Y##M##D_')
filenew = rename(file,agestr) # rename
k+=1
print('renamed',str(k),ext,'files')
# .mp4 videos from android phone in form VID_yyyymmdd_HHMMSS
# just read name to get datetime
# picasa seems to have problem with .mp4, so rename to .mov
ext = '.mp4'
ext2 = '.mov'
files = glob.glob('*'+ext)
k = 0;
for file in files:
# check whether file already has correct name
imatch = check_filename(file)
if imatch == None: # file did not match, need to fix name
dtime = datetime.strptime(file, 'VID_%Y%m%d_%H%M%S'+ext) # datetime from filename
agestr = date2agestr(dtime) # generate age string ('##Y##M##D_')
filenew = rename(file,agestr,ext2) # rename & change extension
k+=1
print('renamed',str(k),ext,'files to',ext2,'files')
# change back to pics directory
#os.chdir(folder_pics)