-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
112 lines (93 loc) · 3.65 KB
/
main.py
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
#! /usr/bin/env python
"""Image Grouper.
Usage:
image-grouper <source_dir> [-o <output_dir>] [-r] [--move] [--exifonly] [-f <format>] [-d]
image-grouper (-h | --help)
image-grouper (-v | --version)
Arguments:
source_dir path to image source directory
Options:
-h --help show this screen
-v --version show version
-o <output_dir> specify output dir
-r read source recursively [default: False]
--move move images instead of copying, source will be deleted,
use it by caution [default: False]
--exifonly read exif only [default: False]
-f <format> output dir name format, specify month for yyyy-mm or day for yyyy-mm-dd [default: month]
-d show debugging info
"""
from docopt import docopt
import os
import time
import shutil
from logger import Logger
import exifread
# what tags use to redate file (use first found)
DT_TAGS = ["Image DateTime", "EXIF DateTimeOriginal", "DateTime"]
def readExifDate(image_path):
"""read date from exif, return in format of ('2005:10:20 23:22:28'),
return None if any error"""
f = open(image_path, 'rb')
try:
tags = exifread.process_file(f, details=False)
for dt_tag in DT_TAGS:
try:
dt_value = '%s' % tags[dt_tag]
logger.info('%s: %s' % (dt_tag, dt_value))
except:
continue
if dt_value:
return exif_info2time(dt_value)
finally:
f.close()
return None
def exif_info2time(ts):
"""changes EXIF date ('2005:10:20 23:22:28') to number of seconds since 1970-01-01"""
tpl = time.strptime(ts + 'UTC', '%Y:%m:%d %H:%M:%S%Z')
return time.mktime(tpl)
def calcOutputDirPath(imageFilePath, isExifOnly, outputParentDir):
date = readExifDate(imageFilePath)
if date:
dt = date
elif not isExifOnly:
logger.info('using file last modified time')
dt = os.path.getmtime(imageFilePath)
else:
dt = None
# %Y-%m by default
dateFormat = '%Y-%m-%d' if args['-f'] == 'day' else '%Y-%m'
# if failed to parse date of image, put it to root of outputParentDir, so
# here we pass an empty string
targetDirName = time.strftime(dateFormat, time.localtime(dt)) if dt else ''
return os.sep.join([outputParentDir, targetDirName])
if __name__ == '__main__':
args = docopt(__doc__, version='0.0.1')
logger = Logger(args['-d'])
logger.info(args)
for (dirpath, dirnames, filenames) in os.walk(os.path.abspath(args['<source_dir>'])):
for filename in filenames:
filepath = os.sep.join([dirpath, filename])
logger.info(filepath)
targetDirName = calcOutputDirPath(filepath, args[
'--exifonly'], os.path.abspath(args['-o']) if args['-o'] else os.path.abspath(args['<source_dir>']))
logger.info('output dir name is %s' % targetDirName)
try:
os.makedirs(targetDirName)
except:
pass
try:
if not args['--move']:
logger.info('coping image from %s to %s' %
(filepath, targetDirName))
shutil.copy2(filepath, targetDirName)
else:
logger.info('moving image from %s to %s' %
(filepath, targetDirName))
shutil.move(filepath, targetDirName)
except:
logger.error('failed to copy/move %s' % filepath)
pass
# no recurse, just top level dir
if not args['-r']:
break