python同时输出名字和时间_Python练习小工具——根据Exif的拍摄时间和设备名批量重命名照片...

[Python] 纯文本查看 复制代码import exifread

from tkinter.filedialog import * #别问我怎么不导入os模块就能 重命名,我也不知道,可能这个tkinter模块包含有os了吧,哈哈

Files_Names={ #全局变量,存储照片绝对路径 和 目录路径(即不包含照片名的路径)

"all_path":[],

"ml_name":""

}

def mainapp(): #创建窗体

app=Tk()

app.title("批量根据exif信息自动重命名照片")

Label(app, text="批量根据exif信息自动重命名照片", font=("微软雅黑", 25, "bold")).pack() # 画标签并设置显示的文字,字体,加粗

Listbox(app, name='l_b', bg="#f2f2f2", fg="red").pack(fill=BOTH,expand=True) # 画列表框并指定名字,方便后续根据名字调用获取Listbox实例,指定背景,前景,显示方式

Button(app, text="选择照片路径", command=ui_update).pack(fill=BOTH) # command指定了当按下按钮,会调用哪个方法

Button(app, text="开始Exif命命名", command=rename).pack(fill=BOTH) # left

app_width = 500 # 设置窗口宽度

app_height = 500 # 设置窗口高度

win_width = int((

app.winfo_screenwidth() - app_width) / 2) # 设置窗口距离左上角原点的 宽度 屏幕总宽度-软件窗口宽度 再除2,即软件距离左侧窗口的宽度 转为整数,因为下面geometry只接受字符串型整数

win_height = int((

app.winfo_screenheight() - app_height) / 2) # 设置窗口距离左上角原点的 高度 屏幕总宽度-软件窗口高度 再除2,即软件距离顶边的高度 转为整数,因为下面geometry只接受字符串型整数

app.geometry("%sx%s+%s+%s" % (app_width, app_height, win_width, win_height)) # 设置窗口显示的宽高度 及 距离原点的长宽度

return app

def ui_update(): #此方法用于把照片所有的路径读到 列表框,当点击按钮《选择照片路径》,就会调用此方法

list_box = a.children["l_b"] # 读取出列表框对象

list_box.delete(0, END) # 删除全部列表内容,防止你点了几次《选择照片路径》,重复添加了几次照片。

Files_Names["ml_name"]=askdirectory() #选择照片所在的目录并存到变量里,后面重命名完成后,调用这个变量,显示文件夹出来

Files_Names["all_path"]=[] #把存了照片的绝对路径的变量清空,防止你批量重命名完一个文件夹后(此时没关闭软件),继续使用去选择下一个文件夹来重命名,如果不清空,将会出错,因为残留有上一次批量重命名的路径名。

if Files_Names["ml_name"]!="": #此判断为了防止你点了《选择照片路径》按钮,又不选择文件夹,直接点了取消,此时返回空,就不执行遍历照片功能。

Files_Names["ml_name"] += "/"

list_name(Files_Names["ml_name"]) # 把选择的目录传入到list_name方法中,进行递归遍历照片文件路径

def list_name(ml_name):

file_names = os.listdir(ml_name) # 根据选择的目录列出里面的照片及目录 返回列表

if file_names != "": # 只要返回的照片和目录路径不为空,防止你犯二,选择了一个没有照片的空目录

list_box = a.children["l_b"] # 读取出列表框对象,下面在循环插入路径到列表框要用对象调用

for i in range(0, len(file_names)): # 列表转换为循环数。

path = os.path.join(ml_name, file_names[i]) # 把目录名ml_name拼接上文件名file_names[i],获得完整路径。

if os.path.isfile(path): # 如果为真,则是文件

list_box.insert(END, path) # 循环插入文件名到列表框

Files_Names["all_path"].append(path) # 完整的照片路径追加到 全局变量列表中

else: # 如果不是文件,那应该是目录,就加上/,再调用自身方法,进行递归列出下一层的文件,很多人在递归这里搞不明白。。。

try:

list_name(path + "/")

except:

print("访问目录出错,可能不是一个目录,或者是奇奇怪怪的文件名")

def rename():

for index,j_file_name in enumerate(Files_Names["all_path"]): #准备循环重命名

with open(j_file_name, 'rb') as f: # 打开照片文件并读取到f中

tags =exifread.process_file(f) # 从f中通过exifread.process_file获取exif信息(返回一个字典类型)

image_exif_time="" #清空exif拍摄时间信息,为下一个照片重命名做准备,不残留上一个照片的拍照时间

image_Make_mode="" #清空exif拍摄时间信息,为下一个照片重命名做准备,不残留上一个照片的手机型号

if "EXIF DateTimeOriginal" in tags.keys(): #如果这个存着拍摄时间的键 存在 上面取出的exif字典里

image_exif_time=tags["EXIF DateTimeOriginal"] #把时间取出来,赋值给变量,准备拿它来当新文件名,下面两个同样道理,都是存着时间的,当判断这个键不存在时,就判断下面两个键有没有时间存着。

elif "EXIF DateTimeDigitized" in tags.keys(): #实践发现,这也是一个拍摄时间

image_exif_time = tags["EXIF DateTimeDigitized"]

elif "Image DateTime" in tags.keys(): #实践发现,这也是一个拍摄时间

image_exif_time = tags["Image DateTime"]

if ":" in str(image_exif_time): #取出来的拍摄时间是 2020:01:01 18:18 这种形式,难看

image_exif_time = str(image_exif_time).replace(":", "-") #换成2020-01-01 18-18 形式

if "Image Make" in tags.keys() and "Image Model" in tags.keys() : #如果存在品牌和 型号,就取出来

image_Make_mode="-"+str(tags["Image Make"])+str(tags["Image Model"])

if image_exif_time!="": #如果有拍摄时间,就进行 拆分目录 和 文件名

img_path="/".join(j_file_name.split("/")[0:-1]) #取出照片目录 D:/ZM/2019.05.11社团周年庆

img_name=j_file_name.split("/")[-1] #取出文件名。 656566.jpg

hz=img_name.split(".")[-1] #取出后缀。 .jpg

else: #如果没有拍摄时间,直接跳到循环尾,进行下一个照片exif时间的提取,不进行重命名了。

continue

try: # try一下,防止出现未知错误 这里要注意,不能写在with里,因为会占用照片文件,导致重命名失败。

new_file_name = ("%s/%s%s.%s") % (img_path, image_exif_time, image_Make_mode, hz)

os.renames(j_file_name, new_file_name)

except: # 当出现未知错误,或者是照片里的exif拍摄时间重复,比如1秒拍了10张,这类照片因为时间一模一样,重命名不了,只能在时间一样的照片后面按顺序加上 数字 来重命名。

for o in range(50): # 防止你相机设备太牛逼,1秒拍了50张,导致时间一模一样的照片,所以设置循环50次,在文件名后面依次加上数字来重命名。

try:

new_file_name = ("%s/%s%s-%s.%s") % (img_path, image_exif_time, image_Make_mode, str(o+ 1), hz)

print("第%d张图片重命名中,疑似名字重复或照片文件损坏,重命名失败,将添加后缀%s继续重命名!50次内若重命名还是失败,将忽略些图片!" % (index, str(o + 1)))

print("原文件名:%s" % j_file_name)

print("预计新文件名:%s\n\n" % new_file_name)

os.renames(j_file_name, new_file_name)

break # 当重命名成功后,立即跳出循环,不用笨笨的循环到50次。

except:

pass

os.startfile(Files_Names["ml_name"]) #所有文件重命名完成后,弹出照片所有的窗口

print("重命名完成!")

a=mainapp()

a.mainloop()

一、安装和使用 Jhead 2.82_绿色英文版 使用时,点击开始菜单-运行命令,在对话框输入: "jhead –命令参数 jpeg文件" 例如: “jhead -de D:\My Pictures\A.jpg” 删除D盘My Pictures文件夹A.jpg文件的exif信息。 “jhead -de D:\My Pictures\*.jpg” 删除D盘My Pictures文件夹所有jpg文件的exif信息。其中星号是通配符。 二、通用指令参数 -te 将其他jpeg文件的eixf导入目标jpeg。例如"jhead –te D:\My Pictures\B.jpg D:\My Pictures\A.jpg" -dc 删除jpeg信息中的备注。注意,jpeg文件有两个备注,一是和其他文件一样的备注,另一个是exif信息中的备注。jhead仅对exif信息有效。 -de 完全删除exif信息。 -du 删除非原始exif信息,例如Photoshop、Turbophoto之类编辑后修改exif留下的信息。 -purejpg 删除所有jpeg文件非必须的信息。相当于-de、-dc和-du的集合,可以将文件减小数k。 -ce 修改文件的jpeg文件头部分备注(此备注并非exif信息)。该指令会打开文本编辑器,并在编辑器关闭时将备注信息存入文件。 -cs 导出备注。例如"jhead –cs D:\1.txt D:\My Pictures\A.jpg" -ci 导入备注。例如"jhead –ci D:\1.txt D:\My Pictures\A.jpg" -cl 直接输入备注。。例如"jhead –cl 我的备注 D:\My Pictures\A.jpg" 三、其他指令 时间日期 -ft 将jpeg文件的“修改时间”修改为exif信息中记录的时间。 -n[] 该指令会将文件修改为exif信息中记录的“创建时间”;如果jpeg文件没有exif或者exif中的创建时间不可用,则将文件修改为文件的“修改时间”。 默认的格式-顺序为MMDD-HHMMSS 格式-顺序参数如下: %d-日(01-31) %H-小时(00-23) %j-一年中的第几天(001-366) %m-月(01-12) %M-分钟(00-59) %S-秒(00-59) %U-一年中的第几周(00-53) %w-星期几(0-6,周日为0) %y-两位数纪年(00-99) %Y-四位数几年 %i-添加数字序号 例如: jhead -n%Y%m%d-%H%M%S d:\*.jpg 将所有jpg文件修改为YYYYMMDD-HHMMSS.jpg的格式。 -nf 与“-n”相同功能相同,不保留原文件。 -a 修改不同扩展的同文件,相机拍摄的avi短片exif信息存储在与其同的thm文件中,可用此指令给avi文件更。一般与“-n”指令共同使用。 -ta 修正时差,例如时差根据时区确定,例如+1:00或者-1:00 -da- 修正日期。日期格式是yyyy:mm:dd、yyyy:nn:dd+hh:mm或者 yyyy:mm:dd+hh:mm:ss。根据前后参数时间差调整exif时间。 -ts 直接修改exif中的拍摄时间,日期-时间格式为yyyy:mm:dd-hh:mm:ss
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值