Python批量重命名iPhone、微信照片,视频-按照拍摄时间重命名

平时用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)

你可能感兴趣的:(python,算法)