根据拍照时间批量修改照片文件名的Python脚本

辛辛苦苦把电脑里好几年的照片上传到云盘以后,发现在云盘里照片文件的创建时间都变成了存入云盘的时间。另外,云盘网页上也无法看到照片的拍照时间(EXIF属性),整理照片时特别不方便。

考虑到多数照片的文件名是由相机自动生成的,例如:IMG_3153.JPG。这样的文件名其实对我们也没有什么实际用处,不如干脆将文件名修改为拍照时间。这样的话,即使照片上传到云盘,也能够很方便的判断照片的时间。

使用Python写了以下脚本,在Mac OS X下验证通过,处理速度非常快。 注:由于拍照时间可以精确到秒,所以这个脚本产生的重名文件名的概率应该是很低的。

#!/usr/bin/env python
# -*- coding: utf-8 -*-  

'''
批量修改照片文件名称的Python脚本程序。
遍历指定目录(含子目录)的照片文件,根据拍照时间将照片文件名修改为以下格式:
2014-03-15_091230.jpg (%Y-%m-%d_%H%M%S)

由于文件名已经精确到秒,理论上重名的概率非常小。
如果需要考虑到重名的问题,可以对本程序进行进一步的优化。

Author: tudaxia.com
Date: 2014-05-13

!该程序需要安装exifread模块,否则无法使用。
例如,Linux/Mac OS X下命令行安装该模块:sudo pip install exifread
'''

import os
import stat
import time
import exifread

MY_DATE_FORMAT = '%Y-%m-%d_%H%M%S'
SUFFIX_FILTER = ['.jpg','.png','.mpg','.mp4','.thm','.bmp','.jpeg','.avi','.mov']
DELETE_FILES = ['thumbs.db','sample.dat']

def isFormatedFileName(filename):
    '判断是否已经是格式化过的文件名'
    try:
        filename_nopath = os.path.basename(filename)
        f,e = os.path.splitext(filename_nopath)
        time.strptime(f, MY_DATE_FORMAT)
        return True
    except ValueError:
        return False
        
def isTargetedFileType(filename):
    '根据文件扩展名,判断是否是需要处理的文件类型'
    filename_nopath = os.path.basename(filename)
    f,e = os.path.splitext(filename_nopath)
    if e.lower() in SUFFIX_FILTER:
        return True
    else:
        return False    

def isDeleteFile(filename):
    '判断是否是指定要删除的文件'
    filename_nopath = os.path.basename(filename)
    if filename_nopath.lower() in DELETE_FILES:
        return True
    else:
        return False   
        
def generateNewFileName(filename):
    '根据照片的拍照时间生成新的文件名(如果获取不到拍照时间,则使用文件的创建时间)'
    try:
    	if os.path.isfile(filename):
            fd = open(filename, 'rb')
        else:
            raise "[%s] is not a file!\n" % filename
    except:
        raise "unopen file[%s]\n" % filename
        
    data = exifread.process_file( fd )
    if data:
        #取得照片的拍摄日期
        try:
            t = data['EXIF DateTimeOriginal']
            #转换成 yyyy-mm-dd_hhmmss的格式
            dateStr = str(t).replace(":","-")[:10] + "_" + str(t)[11:].replace(":","")
        except:
            pass
    else:
        #如果没有取得exif信息,则用图像文件的创建日期作为拍摄日期
        state = os.stat(filename)
        dateStr = time.strftime("%Y-%m-%d_%H%M%S", time.localtime(state[-2]))
    
    dirname = os.path.dirname(filename)
    filename_nopath = os.path.basename(filename)
    f,e = os.path.splitext(filename_nopath)
    
    newFileName = os.path.join(dirname, dateStr + e).lower()
    return newFileName
    

def scandir(startdir):
    '遍历指定目录以及子目录,对满足条件的文件进行改名或删除处理'
    os.chdir(startdir)
    for obj in os.listdir(os.curdir) :
        if os.path.isfile(obj):
            if isTargetedFileType(obj) and isFormatedFileName(obj) == False:
                #对满足过滤条件的文件进行改名处理
                newFileName = generateNewFileName(obj)
                print "rename [%s] => [%s]" % (obj, newFileName)
                os.rename(obj, newFileName)
            elif isDeleteFile(obj):
                #删除制定的文件
                print "delete [%s]: " % obj
                os.remove(obj)
            else:   
                pass

        if os.path.isdir(obj) :
            scandir(obj)
            os.chdir(os.pardir)
    

if __name__ == "__main__":
    path = "/Users/tudaxia/test"
    scandir(path)
Share Comments
comments powered by Disqus