背景需求
作为幼儿园老师,每天都会拍摄大量的一日生活照片,于是手机经常提示“内存不足”。2020年之前,阿夏采用的方法是这样的:
1.QQ-我的文件助手-导出手机相册
2.新建一个个文件夹,根据日期,手动拖拽分类
3.操作烦恼——手动整理照片效率太低
通常是一个月整理一次手机照片。需要一次性新建30个文件夹并手动修改日期,通过目测选择同一天的照片并拖拽,很容易出现照片或文件夹的拖拽错误。搞了几个月整理后,我对这种低效、机械重复感到无比厌烦。
二、实用性测试
通过近一年时间的研究,在实现我的整理需求过程中,我在CSDN找到了两个能够执行成功的照片分类代码,技术有限,我读不懂代码的含义,不会修改,只能完全套用。因此在实际运用中,它们展现了长处,也出现了我难以破解的短板。
(1)第一个:
这是我第一个使用的照片整理代码,它可以将照片从源文档复制到新文档,问题是:1、可以转移照片,但无法转移视频。2、原文档不删除
(2)第二个:
在前者基础上,我找到了可以删除原文档、并且转移照片和视频的程序,问题是:1、我不需要日期下有子文件夹,可是导出的图片和视频依旧保存在“2022-01-02-NONE”文件里(我想让图片和视频直接存在2022-01-02文件下)
三、运用过程
2021年5月-2022年2月,我都是使用博主lidashent的照片分类代码,原始代码如下:
# ————————————————
# 版权声明:本文为CSDN博主「lidashent」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/lidashent/article/details/113919375
# ————————————————
import os,shutil
import time
import datetime
allFileNum = 0
myfile=[]
mydir=[]
movie_file_format=['avi','mpeg','mp4','mov','ProRes','DNxHR','mfx','mkv','wmv','flv','rmvb','webm','asf']
text_file_format=['DOC','PDF','HTML','TXT','HTL','DOCX']
img_file_format=['bmp','jpg','jpeg','png','tif','gif','pcx','tga','exif','fpx','svg','psd',
'cdr','pcd','dxf','ufo','eps','ai','raw','WMF','webp','avif','hdri','flic','emf','ico']
zip_file_format=['rar' ,'zip','7z','CAB','ARJ','LZH','TAR','GZ','ACE','UUE','BZ2','JAR','ISO','MPQ']
music_file_format=['PCM','WAV','AIFF','MP3','AAC','OGG','WMA','FLAC','ALAC','WMA']
this_folder=input("原始路径:").replace("\\",'/')
# this_folder='D:\03照片导出'
those_folder=input("目标路径:").replace("\\",'/')
# those_folder='D:\04照片整理'
def printPath(level, path):
global allFileNum
'''''
打印一个目录下的所有文件夹和文件
'''
# 所有文件夹,第一个字段是次目录的级别
dirList = []
# 所有文件
fileList = []
# 返回一个列表,其中包含在目录条目的名称(google翻译)
files = os.listdir(path)
# 先添加目录级别
dirList.append(str(level))
for f in files:
if (os.path.isdir(path + '/' + f)):
# 排除隐藏文件夹。因为隐藏文件夹过多
if (f[0] == '.'):
pass
else:
# 添加非隐藏文件夹
dirList.append(f)
mydir.append(path + '/' + f)
if (os.path.isfile(path + '/' + f)):
# 添加文件
fileList.append(f)
myfile.append(path + '/' + f)
# 当一个标志使用,文件夹列表第一个级别不打印
i_dl = 0
for dl in dirList:
if (i_dl == 0):
i_dl = i_dl + 1
else:
# print("得到的文件夹",'-' * (int(dirList[0])), dl)
# 打印目录下的所有文件夹和文件,目录级别+1
printPath((int(dirList[0]) + 1), path + '/' + dl)
for fl in fileList:
# print("得到的文件路径",'-' * (int(dirList[0])), fl)
# 随便计算一下有多少个文件
allFileNum = allFileNum + 1
#文件处理
def judge_file(oldPath,location):
def TimeStampToTime(timestamp):
timeStruct = time.localtime(timestamp)
return time.strftime('%Y-%m-%d %H:%M:%S', timeStruct)
def get_file_format(file_path):
file_name=file_path.split("/")[-1]
if file_name.find(".")>0:
file_format=file_name.split('.')[-1]
if file_format.lower() in movie_file_format or file_format.upper() in movie_file_format:
return "视频"
elif file_format.lower() in text_file_format or file_format.upper() in text_file_format:
return "文本"
elif file_format.lower() in img_file_format or file_format.upper() in img_file_format:
return "图片"
elif file_format.lower() in music_file_format or file_format.upper() in music_file_format:
return "音频"
elif file_format.lower() in zip_file_format or file_format.upper() in zip_file_format:
return "压缩"
else:
return "其他"
else:
return "文本"
def move_file(new_dir):
old_file_name = oldPath.split("/")[-1]
# 将文件移动到新文件夹
shutil.move(oldPath, new_dir + '/' + old_file_name) # a->b
print("-"*50+"已完成:%.2f" % ((location + 1) / allFileNum*100))
# ImageDate = datetime.datetime.strftime(time.ctime(os.stat(imgPath).st_mtime), "%Y-%m-%d %H:%M:%S")
a = os.stat(oldPath).st_mtime
#得到文件创建时间,判断文件夹是否存在
creat_time=TimeStampToTime(a)[:-9]
print(creat_time) #str 2021-01-10 10:05:31
folder_format=get_file_format(oldPath)
new_dir="%s/%s/%s"%(those_folder,creat_time,folder_format)
#不存在文件夹则创建文件夹
if not os.path.exists(new_dir):
os.makedirs(new_dir)
move_file(new_dir)
#如果存在就判断是否是重复文件
else :
if oldPath.split("/")[-1] in os.listdir(new_dir):
print("重复文件,略过")
pass
else:
move_file(new_dir)
def do_all():
for i in myfile:
judge_file(i,myfile.index(i))
printPath(1, this_folder)
do_all()
input()
由于本人并不需要将每天拍摄的照片和视频分别保存在“图片”“视频”文件内,因此,将部分涉及格式的内容进行了注释处理。
import os,shutil
import time
import datetime
allFileNum = 0
myfile=[]
# mydir=[]
# movie_file_format=['avi','mpeg','mp4','mov','ProRes','DNxHR','mfx','mkv','wmv','flv','rmvb','webm','asf']
# text_file_format=['DOC','PDF','HTML','TXT','HTL','DOCX']
# img_file_format=['bmp','jpg','jpeg','png','tif','gif','pcx','tga','exif','fpx','svg','psd',
# 'cdr','pcd','dxf','ufo','eps','ai','raw','WMF','webp','avif','hdri','flic','emf','ico']
# zip_file_format=['rar' ,'zip','7z','CAB','ARJ','LZH','TAR','GZ','ACE','UUE','BZ2','JAR','ISO','MPQ']
# music_file_format=['PCM','WAV','AIFF','MP3','AAC','OGG','WMA','FLAC','ALAC','WMA']
this_folder= 'D:\\03照片导出'
# this_folder=input("原始路径:").replace("\\",'/')
those_folder='D:\\04照片整理'
# those_folder=input("目标路径:").replace("\\",'/')
def printPath(level, path):
global allFileNum
'''''
打印一个目录下的所有文件夹和文件
'''
# 所有文件夹,第一个字段是次目录的级别
dirList = []
# 所有文件
fileList = []
# 返回一个列表,其中包含在目录条目的名称(google翻译)
files = os.listdir(path)
# 先添加目录级别
dirList.append(str(level))
for f in files:
if (os.path.isdir(path + '/' + f)):
# 排除隐藏文件夹。因为隐藏文件夹过多
if (f[0] == '.'):
pass
else:
# 添加非隐藏文件夹
dirList.append(f)
# mydir.append(path + '/' + f)
if (os.path.isfile(path + '/' + f)):
# 添加文件
fileList.append(f)
myfile.append(path + '/' + f)
# 当一个标志使用,文件夹列表第一个级别不打印
i_dl = 0
for dl in dirList:
if (i_dl == 0):
i_dl = i_dl + 1
else:
# print("得到的文件夹",'-' * (int(dirList[-1])), dl)
# 打印目录下的所有文件夹和文件,目录级别+1
printPath((int(dirList[0]) + 1), path + '/' + dl)
for fl in fileList:
# print("得到的文件路径",'-' * (int(dirList[-1])), fl)
# 随便计算一下有多少个文件
allFileNum = allFileNum + 1
def judge_file(oldPath,location):
def TimeStampToTime(timestamp):
timeStruct = time.localtime(timestamp)
return time.strftime('%Y-%m-%d %H:%M:%S', timeStruct)
def get_file_format(file_path):
file_name=file_path.split("/")[-1]
# if file_name.find(".")>0:
# file_format=file_name.split('.')[-1]
# if file_format.lower() in movie_file_format or file_format.upper() in movie_file_format:
# return "视频"
# # elif file_format.lower() in text_file_format or file_format.upper() in text_file_format:
# # return "文本"
# elif file_format.lower() in img_file_format or file_format.upper() in img_file_format:
# return "图片"
# elif file_format.lower() in music_file_format or file_format.upper() in music_file_format:
# return "音频"
# elif file_format.lower() in zip_file_format or file_format.upper() in zip_file_format:
# return "压缩"
# else:
# return "其他"
# else:
# return "文本"
def move_file(new_dir):
old_file_name = oldPath.split("/")[-1]
# 将文件移动到新文件夹
shutil.move(oldPath, new_dir + '/' + old_file_name) # a->b
print("-"*50+"已完成:%.2f" % ((location + 1) / allFileNum*100))
# ImageDate = datetime.datetime.strftime(time.ctime(os.stat(imgPath).st_mtime), "%Y-%m-%d %H:%M:%S")
a = os.stat(oldPath).st_mtime
#得到文件创建时间,判断文件夹是否存在
creat_time=TimeStampToTime(a)[:-9]
print(creat_time) #str 2021-01-10 10:05:31
folder_format=get_file_format(oldPath)
new_dir="%s/%s/%s"%(those_folder,creat_time,folder_format)
#不存在文件夹则创建文件夹
if not os.path.exists(new_dir):
os.makedirs(new_dir)
move_file(new_dir)
#如果存在就判断是否是重复文件
else :
if oldPath.split("/")[-1] in os.listdir(new_dir):
print("重复文件,略过")
pass
else:
move_file(new_dir)
def do_all():
for i in myfile:
judge_file(i,myfile.index(i))
printPath(1, this_folder)
do_all()
input()
# ————————————————
# 版权声明:本文为CSDN博主「lidashent」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/lidashent/article/details/113919375
虽然将不需要的内容注释了,但保存时,我发现每天的图片和视频一起保存在‘’日期下的none文件里‘’,而不是直接存在‘’日期‘下面,整理时,我要再次点开none文件,将里面的图片和视频拖到到2022-02-22下,然后再次进行手动分类,整理日期如果很多,这样的重复拖动就显得无聊。
(图片视频在none文件下)
当然,这个代码已经帮助我解决了按日期快速整理照片的需求,提高了时间效率。只是最后我还要通过人工观测将一整天的照片进行分组(难以程序化处理),所以希望把照片视频直接放在日期下,不要有none文件的存在来增加额外工作量。
五、需求实现
在马先生的指导下,3月2日,我开始尝试对博主lidashent的照片分类代码进行解读,将每一段不理解的代码放到百度里搜索可能的含义,并进行注释。在从上到下的注释后,终于在第95行获得了想要的结果。(由于这里解决了,97行后面的代码注释就没有详细解读,以后有机会再研究)
原来日期下有none文件的原因是“新列表定义了三级文件夹( new_dir="%s/%s%s" 路径-日期-格式),如果将新列表定义两级( new_dir="%s/%s"路径-日期),就可以实现照片视频统一放在日期目录下的结果。
具体代码
import os,shutil
import time
import datetime
allFileNum = 0# 所有文件数量从0开始
myfile=[]# 我的文件
mydir=[]# 我的列表
movie_file_format=['avi','mpeg','mp4','mov','ProRes','DNxHR','mfx','mkv','wmv','flv','rmvb','webm','asf']# 视频格式
text_file_format=['DOC','PDF','HTML','TXT','HTL','DOCX']# 文本格式
img_file_format=['bmp','jpg','jpeg','png','tif','gif','pcx','tga','exif','fpx','svg','psd',
'cdr','pcd','dxf','ufo','eps','ai','raw','WMF','webp','avif','hdri','flic','emf','ico']# 图片格式
zip_file_format=['rar' ,'zip','7z','CAB','ARJ','LZH','TAR','GZ','ACE','UUE','BZ2','JAR','ISO','MPQ']# 压缩格式
music_file_format=['PCM','WAV','AIFF','MP3','AAC','OGG','WMA','FLAC','ALAC','WMA']# 音乐格式
this_folder= 'D:\\03照片导出' # 整理前的照片所在文件夹,原始路径:
# this_folder=input("原始路径:").replace("\\",'/')
those_folder='D:\\04照片整理'# 整理后的照片所在文件夹(原照片删除),目标路径:
# those_folder=input("目标路径:").replace("\\",'/')
def printPath(level, path):# 定义输出路径(层级,路径字符串)
global allFileNum # 返回allFileNum的全局变量
'''''
打印一个目录下的所有文件夹和文件
'''
# 所有文件夹,第一个字段是次目录的级别
dirList = [] # 目录清单
# 所有文件
fileList = []
# 返回一个列表,其中包含在目录条目的名称(google翻译)
files = os.listdir(path)
# 先添加目录级别
dirList.append(str(level))
for f in files:
if (os.path.isdir(path + '/' + f)): # os.path.isdir()用于判断对象是否为一个目录
if (f[0] == '.'):# 排除隐藏文件夹。因为隐藏文件夹过多
pass
else:
# 添加非隐藏文件夹
dirList.append(f)
# mydir.append(path + '/' + f)
if (os.path.isfile(path + '/' + f)):
# 添加文件
fileList.append(f)
myfile.append(path + '/' + f)
# 当一个标志使用,文件夹列表第一个级别不打印
i_dl = 0
for dl in dirList:
if (i_dl == 0):
i_dl = i_dl + 1
else:
# print("得到的文件夹",'-' * (int(dirList[-1])), dl)
# 打印目录下的所有文件夹和文件,目录级别+1
printPath((int(dirList[0])+1), path + '/' + dl)
for fl in fileList:
# print("得到的文件路径",'-' * (int(dirList[-1])), fl)
# 随便计算一下有多少个文件
allFileNum = allFileNum + 1
def judge_file(oldPath,location): # 定义判断文件(老文件,位置)
def TimeStampToTime(timestamp):# 定义时间转戳时间(时间戳)
timeStruct = time.localtime(timestamp)#时间结构体等于,格式化时间戳为本地的时间(时间戳)
return time.strftime('%Y-%m-%d %H:%M:%S', timeStruct)#返回本地时间戳(结构累心,时间结构体)
def get_file_format(file_path): # 定义获取后的文件格式(文件路径)
file_name=file_path.split("/")[-1] #文件名称等于 文件路径 的最后一段 split("/")[-1] 以‘/ ’为分割f符,保留最后一段
# if file_name.find(".")>0:
# file_format=file_name.split('.')[-1] #文件名称等于 文件路径 的最后一段
# if file_format.lower() in movie_file_format or file_format.upper() in movie_file_format:
# return "视频"
# # elif file_format.lower() in text_file_format or file_format.upper() in text_file_format:
# # return "文本"
# elif file_format.lower() in img_file_format or file_format.upper() in img_file_format:
# return "图片"
# elif file_format.lower() in music_file_format or file_format.upper() in music_file_format:
# return "音频"
# elif file_format.lower() in zip_file_format or file_format.upper() in zip_file_format:
# return "压缩"
# else:
# return "其他"
# else:
# return "文本"
def move_file(new_dir):#定义转移文件 新的列表
old_file_name = oldPath.split("/")[-1]#老文件名等于老路径的最后一段
# 将文件移动到新文件夹
shutil.move(oldPath, new_dir + '/' + old_file_name) # a->b
print("-"*50+"已完成:%.2f" % ((location + 1) / allFileNum*100))
# ImageDate = datetime.datetime.strftime(time.ctime(os.stat(imgPath).st_mtime), "%Y-%m-%d %H:%M:%S")
a = os.stat(oldPath).st_mtime # 文件时间戳 os.stat(老路径文件).st_mtime
#得到文件创建时间,判断文件夹是否存在
creat_time=TimeStampToTime(a)[:-9]
# 创造时间戳
print(creat_time) #打印创造的时间 str 2021-01-10 10:05:31
folder_format=get_file_format(oldPath)
# 新列表展示为三段式结构——整理后的路径(一级文件夹),创造的时间(二级文件夹),文件格式(图片 视频等 三级文件夹)
# new_dir="%s/%s/%s"%(those_folder,creat_time,folder_format)
# 阿夏需要两级文件夹(整理后的路径(一级文件夹),创造的时间(二级文件夹)里面装了混合的照片和视频。手动整理)
new_dir="%s/%s"%(those_folder,creat_time)
#不存在文件夹则创建文件夹
if not os.path.exists(new_dir):
os.makedirs(new_dir)
move_file(new_dir)
#如果存在就判断是否是重复文件
else :
if oldPath.split("/")[-1] in os.listdir(new_dir):
print("重复文件,略过")
pass
else:
move_file(new_dir)
def do_all():
for i in myfile:
judge_file(i,myfile.index(i))
printPath(1, this_folder)
do_all()
input()
# ————————————————
# 版权声明:本文为CSDN博主「lidashent」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/lidashent/article/details/113919375
鸣谢:
感谢CSDN博主「lidashent」的原创文章为我的班级工作(照片整理)带来的便利,这也提醒我需要真正读懂代码,才能学以致用,自行修改实现自己的需求。