-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMediaFilePrefixer.py
More file actions
161 lines (140 loc) · 5.43 KB
/
MediaFilePrefixer.py
File metadata and controls
161 lines (140 loc) · 5.43 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# This script was developed to allow better storage of images:
# 1) Set Created and Modified Date to match the Date Taken [With a little help from: https://gist.github.com/ikoblik/7089165]
# 2) Based on the CreatedDate, add an ordered prefix to the picture name to allow cross-system sorting#
#
# Usage:
# # 1a) Update the Created and Modified DateTimes when there is a DateTaken provided (DateTimeOriginal) - in current folder
# python MediaFilePrefixer.py setTimestamps
# # 1b) Update the Created and Modified DateTimes for images stored in a different folder (script converts proper directory indication)
# python MediaFilePrefixer.py setTimestamps 'D:/Pictures/Event'
#
# # Update file names based on the created date
# # 2a) Add prefix to file names (including movies) based on Created Date - in current folder
# python MediaFilePrefixer.py prefixFiles
# # 2b) Add prefix to file names (including movies) based on Created Date - in specified folder
# python MediaFilePrefixer.py prefixFiles 'D:/Pictures/Event'
#
# @Author Reinier van den Assum
# @Created August 2019
import os, stat, time, re, glob, sys
from stat import *
from exif import Image
from datetime import datetime, timedelta
__dir__ = '.'
__dateFormat__ = '%Y-%m-%d %H:%M:%S'
#####
# UTIL METHODS
#####
# Handle File Extensions
allowed_extensions = [ "jpg", "jpeg", "png", "gif" ] + [ "mov", "mp4" ]
def getExtension( filename ):
return os.path.splitext( filename )[1][1:].strip().lower()
# Only return existing Files of allowed extensions
def fileFilter( fileName ):
return os.path.isfile and getExtension( fileName ) in allowed_extensions
def printTime( t ):
return time.asctime( time.localtime( t ) )
def origFileName( fileName, length ):
return re.sub( r'^([0-9]{'+ str( length ) +'}\_)', '', fileName )
def populatePrefix( i, length ):
return str( i ).zfill( length ) + '_'
def renameFiles( sortedFileList ):
# Get the maximum length of the prefix
lenPrefix = len( str( len( sortedFileList ) ) )
i = 1;
for fileName in sortedFileList:
newFN = populatePrefix( i, lenPrefix ) + origFileName( fileName, lenPrefix )
print( newFN )
os.rename( __dir__ + '/' + fileName, __dir__ + '/' + newFN )
i += 1
######
# EXIF METHODS
######
def getExifCreationDate( path ):
"""Gets the earliest date from the file's EXIF header, returns time tuple"""
timeStamp = None
try:
with open( path, 'rb' ) as image_file:
my_image = Image( image_file )
originalTime = my_image.datetime_original
if( originalTime ):
timeStamp = datetime.strptime( originalTime, __dateFormat__ )
except Exception as e :
print( 'Failed to retrieve datetime_original via Exif for '+ path.replace( __dir__, '' ) )
print( '>> '+ str( e ) )
return timeStamp
# sometimes exif lib failes to retrieve data
if( not timeStamp ):
response = os.popen( 'exif' + ' -x "%s"' % path, 'r' )
lines = response.read()
matches = re.findall('<Date_and_Time.+?>(.*?)</Date_and_Time.+?>', lines)
if( len( matches ) ) :
timeStamp = min( * [datetime.strptime( x, __dateFormat__ ) for x in matches ] )
return timeStamp
def getFileDates(path):
"""Returns a dictionary of file creation (ctime), modification (mtime), exif (exif) dates"""
dates = {}
dates['exif'] = getExifCreationDate(path)
dates['mtime'] = datetime.fromtimestamp( os.path.getmtime( path ) )
dates['ctime'] = datetime.fromtimestamp( os.path.getctime( path ) )
if not dates['exif']:
dates['exif'] = min( dates['mtime'], dates['ctime'] )
return dates
def setFileDates( path, dates ):
"""Sets file modification and creation dates to the specified value"""
newTime = time.mktime( dates['exif'].timetuple() )
# update modified and accessed time
os.utime( path, ( newTime, newTime ) )
try:
# update created time
from win32_setctime import setctime
setctime( path, newTime )
return 'CMA'
except:
return 'MA !Created'
#####
# MAIN METHODS
#####
# python MediaFilePrefixer.py rename
def rename():
print( '== Start adding prefixes to images and video files ==' )
print( '== Folder '+ __dir__ )
# Get Images (files and correct extension)
imageList = filter( fileFilter, os.listdir( __dir__ ) )
# Sort Images by Created Date and Rename files
renameFiles( sorted( imageList, key=lambda p: os.stat( __dir__ + '/' + p ).st_ctime ) )
def setTimestamps():
print( '== Start running setTimestamps ==' )
print( '== Folder '+ __dir__ )
# Get Images (files and correct extension)
imageList = filter( fileFilter, os.listdir( __dir__ ) )
for fileName in imageList:
result = ''
fullPath = __dir__ + '/' + fileName
dates = getFileDates( fullPath )
if( dates[ 'exif' ] ):
# calculate difference between created and modify date
cmp_time = lambda x, y: abs( x - y ) > timedelta(minutes=10)
diff = [ cmp_time( dates[x], dates['exif'] ) for x in ('mtime', 'ctime') ]
if( sum( diff ) ):
result += dates['exif'].strftime( __dateFormat__ ) + ' vs. '+ dates['mtime'].strftime( __dateFormat__ ) + ' vs. '+ dates['mtime'].strftime( __dateFormat__ )
result += ' '+ setFileDates( fullPath, dates )
else:
result = 'Less than 10 minutes difference between dates'
else:
result += 'No EXIF found'
print( fileName + ' - ' + result )
## EXECUTION
try:
args = sys.argv
methodName = args[1]
if len( args ) == 3:
__dir__ = args[2].replace( '\\', '/' ) # Replace Windows to Unix file references
if methodName == 'prefixFiles' :
rename();
elif methodName == 'setTimestamps':
setTimestamps();
else:
print('No method selected')
except Exception as e:
print( e )