Welcome, guest | Sign In | My Account | Store | Cart

Looks at a directory hive, finds .JPGs with EXIF info, and sorts them in a new directory structure by camera model, year, month, and optionally, date. Imports EXIF.py and dirwalk.py in addition to standard Python modules.

Python, 133 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""
---------------------------------------------------------------------------------------------------
Filename:       PhotoLibrarian.py
Author:         Alex Harden
Release Date:   2007-03-26
Description:    Iterates through a directory tree, reading the EXIF data from each JPG. Parses the
                date/time from EXIF data, and copies the photo using the date/time value into a
                new camera/year/month-based tree.  Additional sort by day available.
Attributions:   Ideas and code borrowed from Chad Cooper's RenameCopyPhotos.py:
                http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/500266
                EXIF.py: http://sourceforge.net/projects/exif-py/
                Dirwalk.py borrowed from the ActiveState Python Cookbook:
                http://code.activestate.com/recipes/105873/
Changelog:      2007-03-26: Initial 1.0 release.
---------------------------------------------------------------------------------------------------
"""

import string, sys, traceback, datetime, time
import EXIF, os, shutil
import dirwalk

inputDir = 'D:/photos'          #root directory that will be parsed (includes subdirectories)
outputDir = 'D:/photolibrary'   #our output directory (should be present before script is run)
fileExt = '.JPG'                #restrict to JPGs (we need EXIF data)
dateSort = 0                    #additional directory per date? 1=yes, 0=no
pictureList = dirwalk.dirwalk(inputDir)
count = 0

def FilePic(myPicture,myOutputDir,myDateSort):
    """
    Files the specified picture in the OutputDir according to EXIF Camera Model and date:
    /myOutputDir
        /<EXIF Camera Model>
            /<year>
                /<month>
                    /<date>  (optional)
                        /<myPicture>
    """
    # Check for/make dirs for file to go into
    # If dir already exists, use it - if it doesn't exist, then create it

    try:
        f=open(myPicture, 'rb')
        tags=EXIF.process_file(f)
        myFilename=os.path.basename(myPicture)
        datestr = str(tags['EXIF DateTimeDigitized'])
        datestr = datestr.split(' ')
        dt = datestr[0]  # date
        tm = datestr[1]  # time
        # Date
        y = dt.split(':')[0]    # year
       
        if len(dt.split(':')[1]) < 2:   # month
            m = str('0') + dt.split(':')[1] 
        else:
            m = dt.split(':')[1]
           
        if len(dt.split(':')[2]) < 2:   # day
            d = str('0') + dt.split(':')[2] 
        else:
            d = dt.split(':')[2]

        # Time
        h = tm.split(':')[0]  # hour
        min = tm.split(':')[1]  # minute
        s = tm.split(':')[2]  # second

        camera=str(tags['Image Model'])
        if os.path.isdir(myOutputDir + '/' + camera) != 1:
            os.mkdir(myOutputDir + '/' + camera)
        if os.path.isdir(myOutputDir + '/' + camera + '/' + y) != 1:
            os.mkdir(myOutputDir + '/' + camera + '/' + y)
        if os.path.isdir(myOutputDir + '/' + camera + '/' + y + '/' + m) != 1:
            os.mkdir(myOutputDir + '/' + camera + '/' + y + '/' + m)
        if dateSort:
            if os.path.isdir(myOutputDir + '/' + camera + '/' + y + '/' + m + '/' + d) != 1:
                os.mkdir(myOutputDir + '/' + camera + '/' + y + '/' + m + '/' + d)

        # Copy file, renaming it with new filename
        if myDateSort:
            myNewFilePath=myOutputDir + '/' + camera + '/' + y + '/' + m + '/' + d + '/' + myFilename
        else:
            myNewFilePath=myOutputDir + '/' + camera + '/' + y + '/' + m + '/' + myFilename

        print 'New File: %s' % (myNewFilePath)
        shutil.copyfile(myPicture,myNewFilePath)
            
        # Set modified time to date photo was digitized
        myCurrentTime = datetime.datetime.now()
        myCurrentTime = int(time.mktime(myCurrentTime.timetuple()))
        myDigitizedTime = datetime.datetime(int(y), int(m), int(d), int(h), int(min), int(s))
        myDigitizedTime = int(time.mktime(myDigitizedTime.timetuple()))
        myTimes=(myCurrentTime,myDigitizedTime)
        os.utime(myNewFilePath,myTimes)
    except:
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n    " + \
            str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"

def Timer(start, end):
    """
    Calculates the time it takes to run a process, based on start and finish times
    ---------------------------------------------------------------------------------------------
    Inputs:
    start:        Start time of process
    end:          End time of process
    ---------------------------------------------------------------------------------------------
    """
    elapsed = end - start
    # Convert process time, if needed
    if elapsed <= 59:
        time = str(round(elapsed,2)) + " seconds\n"
    if elapsed >= 60 and elapsed <= 3590:
        min = elapsed / 60
        time = str(round(min,2)) + " minutes\n"
    if elapsed >= 3600:
        hour = elapsed / 3600
        time = str(round(hour,2)) + " hours\n"
    return time

##### RUN #####

if __name__ == '__main__':
    start = time.clock()
    for picture in pictureList:
        if string.upper(picture[-4:]) == fileExt:
            FilePic(picture,outputDir,dateSort)                    
            count = count + 1
    finish = time.clock()
    
    print '\nProcessing done in ', Timer(start, finish)
    print 'Images processed: ', str(count)