平时用iphone手机,也用微信,经常从微信保存一些照片,视频到手机里。时间长了照片比较多,分不清是哪天拍摄的,或者保存的,所以平时我喜欢用时间命名照片,视频。
最近和我女朋友分手了,在一起的一些合照需要存档,按照月份分类存储。
本来想通过百度网盘,百度网盘上传后有两个问题,第一:不安全,不想把私人照片存储到网上,第二:百度网盘存储的实况图片会变成livp结尾的文件,虽然说可以解压成一个jpg和一个mov,我不喜欢这样的处理方式。所以放弃了百度网盘。
其次通过iphone手机,将手机的照片导入到mac电脑上的照片里,可以把照片导出到硬盘中,有两种方式,一种是照片,jpg格式,一种是未修复的原片,我本人比较喜欢原片,存储空间小,保留原汁原味,heic格式。导出的文件命名也不规范。所以我在网上找到一个python程序,但是程序有点问题,一不支持视频,特别是按照视频的媒体创建时间命名,另外一个是如果命名冲突,没有处理。所以我把这个程序修改了,完美解决了我的问题,分享给大家。
程序是从网上找的,本人进行了完善,修改,注释等没有修改,保留原作者的。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
批量修改照片文件名称的Python脚本程序。
遍历指定目录(含子目录)的照片文件,根据拍照时间将照片文件名修改为以下格式:
20140315_091230.jpg (%Y%m%d_%H%M%S)
由于文件名已经精确到秒,理论上重名的概率非常小。
如果需要考虑到重名的问题,可以对本程序进行进一步的优化。
!该程序需要安装exifread模块,否则无法使用。
例如,Linux/Mac OS X下命令行安装该模块:sudo pip install exifread
2022年10月12日 wl 修改
'''
import os
import stat
import time
import exifread
import json
from pymediainfo import MediaInfo
from datetime import datetime, timedelta
MY_DATE_FORMAT = '%Y%m%d_%H%M%S'
path = "/Users/xxxx/Documents/test"
SUFFIX_FILTER = ['.jpg', '.mpg', '.mp4', '.thm', '.bmp', '.jpeg', '.avi', '.mov', '.heic', '.png']
DELETE_FILES = ['thumbs.db', 'sample.dat']
PIC_FILTER = ['.jpg', '.bmp', '.jpeg', '.heic', '.png']
MOVIE_FILTER = ['.mp4', '.avi', '.mov']
def isPicFileType(filename):
# 根据文件扩展名,判断是否是需要处理的文件类型
filename_nopath = os.path.basename(filename)
f, e = os.path.splitext(filename_nopath)
if e.lower() in PIC_FILTER:
return True
else:
return False
def isMovieFileType(filename):
# 根据文件扩展名,判断是否是需要处理的文件类型
filename_nopath = os.path.basename(filename)
f, e = os.path.splitext(filename_nopath)
if e.lower() in MOVIE_FILTER:
return True
else:
return False
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 get_file_date(filepath, format):
media_info = MediaInfo.parse(filepath)
data = media_info.to_json()
print("data111:" + data)
d = json.loads(data)
x = d.get("tracks")
print(x)
temp_time = (x[0].get("comapplequicktimecreationdate"))
beijing_time = ""
if not temp_time is None:
temp_time = temp_time.replace("UTC ", "")
temp_time = temp_time.replace("T", " ")
temp_time = temp_time.replace("+0800", "")
beijing_time = datetime.strptime(temp_time, "%Y-%m-%d %H:%M:%S")
return str(beijing_time)
else:
temp_time = (x[0].get("encoded_date"))
if temp_time is None:
temp_time = (x[0].get("file_last_modification_date"))
temp_time = temp_time.replace("UTC ", "")
beijing_time = datetime.strptime(temp_time, "%Y-%m-%d %H:%M:%S") + timedelta(hours=8)
return str(beijing_time)
return beijing_time;
def generateNewFileName(filename):
# print("filename" + filename)
dateStr = ""
# print("dateStr 1:" + dateStr)
# 如果是图片
if isPicFileType(filename) == True:
# 根据照片的拍照时间生成新的文件名(如果获取不到拍照时间,则使用文件的创建时间)
dateStr = ""
if dateStr == "":
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)
FIELD = 'EXIF DateTimeOriginal'
# print("aa")
if data:
if FIELD in data:
# print("\nstr(data[FIELD]): %s" %(str(data[FIELD]))) # 获取到的结果格式类似为:2018:12:07 03:10:34
# print("\nstr(data[FIELD]).replace(':', '').replace(' ', '_'): %s" %(str(data[FIELD]).replace(':', '').replace(' ', '_'))) # 获取结果格式类似为:20181207_031034
# print("\nos.path.splitext(filename)[1]: %s" %(os.path.splitext(filename)[1])) # 获取了图片的格式,结果类似为:.jpg
new_name = str(data[FIELD]).replace(':', '').replace(' ', '_') + os.path.splitext(filename)[1]
# print("\nnew_name: %s" %(new_name)) # 20181207_031034.jpg
time1 = new_name.split(".")[0][:13]
new_name2 = new_name.split(".")[0][:8] + '_' + filename
# print("\nfilename: %s" %filename)
print("\n%s的拍摄时间是: %s年%s月%s日%s时%s分" % (
filename, time1[0:4], time1[4:6], time1[6:8], time1[9:11], time1[11:13]))
# 可对图片进行重命名
new_full_file_name = os.path.join(path, new_name2)
dateStr = str(data[FIELD])
dateStr = dateStr.replace("-", "").replace(":", "").replace("/", "").replace(" ", "_")
# 如果没有取得exif信息,则用图像文件的创建日期作为拍摄日期
if dateStr == "":
state = os.stat(filename)
dateStr = time.strftime(MY_DATE_FORMAT, time.localtime(state[- 2]))
# 如果是视频
elif isMovieFileType(filename) == True:
# 取媒体生成日期
dateStr = str(get_file_date(filename, MY_DATE_FORMAT))
dateStr = dateStr.replace("-", "").replace(":", "").replace(" ", "_")
print("dateStr 2:" + dateStr)
else:
print("else")
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("newFileName:" + newFileName)
if os.path.exists(newFileName) == False:
print("rename [%s] => [%s]" % (obj, newFileName))
#os.rename(obj, newFileName)
else:
filename_nopath = os.path.basename(newFileName)
f, e = os.path.splitext(filename_nopath)
for i in range(100):
newFileName = f + "(" + str(i) + ")" + e
if os.path.exists(newFileName) == False:
print("rename [%s] => [%s]" % (obj, newFileName))
#os.rename(obj, newFileName)
break
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__":
scandir(path)