Skip to content

Instantly share code, notes, and snippets.

@otger
Forked from nerdtalker/EXIFmover.py
Last active August 29, 2015 13:57
Show Gist options
  • Save otger/9765072 to your computer and use it in GitHub Desktop.
Save otger/9765072 to your computer and use it in GitHub Desktop.
# Name: EXIFmover
# Forked from EXIFmover.py by Brian Klug (@nerdtalker / [email protected])
# Purpose:
# Move Files into directory based on dates
# Designed to un-clusterfuck the Dropbox camera upload directory which is a mess as all files are
# uploaded to same folder.
# Moves files into /YEAR/MONTH eg /2014/03
# Creates directory if it doesn't exist, moves into that directory if it exists
# Files without "YYYY-mm-dd" pattern on its name are scanned looking for exif data
# Files without EXIF are keep at root folder
# Only files with valid extensions are moved
# This is experimental and one-way in a destructive sense, I take no responsibility
# if this absolutely destroys your directory structure for some reason
# I STRONGLY recommend making a copy of Camera Uploads, then running this on the copy, first
# Requires EXIF-PY to be installed and importable in order to check exif. If all your files are named using
# the "YYYY-mm-dd" pattern, there is no need to have EXIF-PY installed
# EXIF-PY can be obtained from https://github.com/ianare/exif-py or using pip: "sudo pip install ExifRead"
# Run simply inside "Camera Upload" folder or whatever you have the media you want to organize
# (eg from ipython "run exifmover.py" inside "Camera Upload")
# or "python exifmover.py"
# Tested on Ubuntu
# Extremely fast: Sorted more than 1400 pictures ranging 4 years in less than a second
try:
import exifread
except:
exifread = None
print "exifread was not found, exif data won't be used"
import os
import time
import re
start_time = time.time()
current_path = os.path.abspath(os.getcwd())
# current_path = "/home/otger/Dropbox/Camera Uploads"
file_names = os.listdir(current_path)
print "Found {0} items on folder {1}".format(len(file_names), current_path)
valid_extensions = ["png", "jpg", "jpeg", "mp4"]
## expression matches: YYYY-mm-dd
re_date = re.compile(r"(\d{4})[:\-\.]?(\d{2})[:\-\.]?\d{2}")
for fname in file_names:
file_path = os.path.join(current_path, fname)
if os.path.isfile(file_path):
if fname.split('.')[-1] in valid_extensions:
year = month = None
fname_date = re_date.search(fname)
if fname_date:
(year, month) = fname_date.groups()
elif exifread:
f = open(file_path)
try:
tags = exifread.process_file(f)
except Exception, ex:
print "Couldn't read tags on " + fname
print ex.message
continue
finally:
f.close()
exif_date = re_date.search(str(tags.get("Image DateTime", "NA")))
if not exif_date:
exif_date = re_date.search(str(tags.get("EXIF DateTimeOriginal", "NA")))
if not exif_date:
print "Couldn't find date on exif for " + fname
continue
(year, month) = exif_date.groups()
print file_path + "date extracted by exif: {0}-{1}".format(year,month)
else:
print "exifread not found, skipping " + file_path
dst_path = os.path.join(current_path, year, month)
dst_file_path = os.path.join(dst_path, fname)
# print "{0} would be moved to {1}".format(fname, dst_path)
if not os.path.exists(dst_path):
print "Creating folder: " + dst_path
try:
os.makedirs(dst_path)
except Exception, ex:
print "Failed to create folder " + dst_path
print ex.message
try:
print "Moving from {0} to {1}".format(file_path, dst_file_path)
os.rename(file_path, dst_file_path)
except Exception, ex:
print "Oh noes. That didn't work for some reason:"
print ex.message
else:
print "Skipping " + file_path
else:
print "Not a file: " + file_path
print 'Done. Execution took {:0.3f} seconds'.format((time.time() - start_time))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment