Using ExifRead on reapting filenames

1172
8
Jump to solution
07-23-2019 12:23 PM
JaredPilbeam2
MVP Regular Contributor

Hello,

I have a lot of JPEGs in a Windows directory. In most cases these JPEGs do not have similar filenames. On the other hand, there are some repeats:

Using exifread, I'm appending the 'date taken' to the end of the seven digit number of the filenames. This script gets me close, but it's not exactly doing what I want. It skips the files with similar names (e.g. 7400010 (2), 7400010b). Also, after running the script I'm having trouble avoiding the '.' of the file extension. Ideally, I'd like every filename to have this structure: 7400010_2018-04-25. And as far as the files with similar names goes, how do I preserve the (2) and the b?

"""
Loops through folder and adds the 'Date Taken' from JPG
"""

import arcpy, sys
import exifread
from exifread import exif
import os
##import time
from datetime import datetime

im = r"\\path\to\pics2\CH74"

for root, dirnames, filenames in os.walk(im): #iterate directory
    for fname in filenames:
        if fname.endswith('.JPG'):
            with open(os.path.join(root, fname), 'rb') as image: #file path and name
                exif = exifread.process_file(image)
                dt = str(exif['EXIF DateTimeOriginal']) #get 'Date Taken' from JPG
                ds = time.strptime(dt, '%Y:%m:%d %H:%M:%S')
                nt = time.strftime("%Y-%m-%d",ds)
                newname = fname[0:8] + "_" + nt + ".jpg"

                image.close()
                os.rename(os.path.join(root,fname), os.path.join(root,newname))‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Here's how the filenames look after running this script:

0 Kudos
1 Solution

Accepted Solutions
RandyBurton
MVP Alum

Another approach, just testing file names:

fn = [ '7400010 (2).jpg',
       '7400010.jpg',
       '7400015b.jpg' ]

for f in fn:
    print f[:-4].replace(' ','_').replace('(','').replace(')','').replace('.','') + '_' + 'date'

# prints
7400010_2_date
7400010_date
7400015b_date‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

8 Replies
JoshuaBixby
MVP Esteemed Contributor

What about:

newname = fname[0:8] + "_" + nt + fname[8:] + ".jpg"
JaredPilbeam2
MVP Regular Contributor

Joshua,

that appended JPG to the end of the date and skipped the repeats:

0 Kudos
RandyBurton
MVP Alum

Another approach, just testing file names:

fn = [ '7400010 (2).jpg',
       '7400010.jpg',
       '7400015b.jpg' ]

for f in fn:
    print f[:-4].replace(' ','_').replace('(','').replace(')','').replace('.','') + '_' + 'date'

# prints
7400010_2_date
7400010_date
7400015b_date‍‍‍‍‍‍‍‍‍‍‍
JaredPilbeam2
MVP Regular Contributor

Randy,

that works nice, but is it possible to put the whole directory into a list?

0 Kudos
JaredPilbeam2
MVP Regular Contributor

I tried this, but the repeats were still skipped:

for root, dirnames, filenames in os.walk(im): #iterate directory
    for fname in filenames:
        if fname.endswith('.JPG'):
            with open(os.path.join(root, fname), 'rb') as image: #file path and name
                exif = exifread.process_file(image)
                dt = str(exif['EXIF DateTimeOriginal']) #get 'Date Taken' from JPG
                ds = time.strptime(dt, '%Y:%m:%d %H:%M:%S')
                nt = time.strftime("%Y-%m-%d",ds)
                newname = fname[:-4].replace(' ','_').replace('(','').replace(')','').replace('.','') + '_' + nt + ".jpg"
                print(newname)‍‍‍‍‍‍‍‍‍‍

prints:

7400010_2018-04-25.jpg
7400015_2018-04-25.jpg
7400016_2018-04-25.jpg
7400017_2018-04-25.jpg‍‍‍‍‍‍‍‍
...
0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Python strings are case sensitive:

>>> 'file.jpg'.endswith('.JPG')
False

Maybe try:

>>> 'file.jpg'.endswith(('.JPG', '.jpg'))
True

JaredPilbeam2
MVP Regular Contributor

That did it, thanks!

for root, dirnames, filenames in os.walk(im): #iterate directory
    for fname in filenames:
        if fname.endswith(('.JPG', '.jpg')):
            with open(os.path.join(root, fname), 'rb') as image: #file path and name
                exif = exifread.process_file(image)
                dt = str(exif['EXIF DateTimeOriginal']) #get 'Date Taken' from JPG
                ds = time.strptime(dt, '%Y:%m:%d %H:%M:%S')
                nt = time.strftime("%Y-%m-%d",ds)
                newname = fname[:-4].replace(' ','_').replace('(','').replace(')','').replace('.','') + '_' + nt + ".jpg"
                #print(newname)

                image.close()
                os.rename(os.path.join(root,fname), os.path.join(root,newname))
0 Kudos
RandyBurton
MVP Alum

I had a script that did a similar rename.  I made a few changes to work in my earlier comment.  I had used the exif tag 'Image DateTime', but it should work with 'EXIF DateTimeOriginal'.  You want to add error checking to insure that the exif tag is valid. If you have multiple directories, then use os.walk. Just another approach; hope it helps.

import os, glob

import exifread
# info on exifread at https://pypi.org/project/ExifRead/

path = r'C:\Path\to\jpeg\directory'

for filename in glob.glob(os.path.join(path, '*.jpg')):
    print '{} - renamed to: '.format(filename)
    f = open(filename, 'rb') # open read only, binary
    tags = exifread.process_file(f)
    f.close()
    # print tags['Image DateTime']
    # print filename[:-4].replace(' ','_').replace('(','').replace(')','').replace('.','')
    # print str(tags['Image DateTime']).replace(':','-').replace(' ','_')[:10]
    newname = os.path.join(path, '{}_{}.jpg'.format(
        filename[:-4].replace(' ','_').replace('(','').replace(')','').replace('.',''), # reformatted filename
        str(tags['Image DateTime']).replace(':','-').replace(' ','_')[:10])) # year-mo-dy from exif
    print '{}\n'.format(newname)
    os.rename(filename, newname)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍