python脚本将照片按时间线整理

news2024/9/19 10:37:28

说明:有一次自己瞎折腾,然后把服务器相册搞崩了,后来做了备份同步给找了回来,但是相册的时间线全乱了,看起来非常难受。所以就想通过文件夹的形式把照片重新分类,分类后的结构如下(红色字体为文件夹):

未分类
2023
├── 202301
│ ├── 图片1.jpg
│ ├── 图片2.jpg
│ └── 图片3.jpg
├── 202302
│ ├── 图片4.jpg
│ ├── 图片5.jpg
│ └── 图片6.jpg
└── …
├── …
├── …
└── …
2024
├── 202401
│ ├── 图片1.jpg
│ ├── 图片2.jpg
│ └── 图片3.jpg
├── 202402
│ ├── 图片4.jpg
│ ├── 图片5.jpg
│ └── 图片6.jpg
└── …
├── …
├── …
└── …

在这里插入图片描述

import os
import shutil
from PIL import Image
from PIL.ExifTags import TAGS

# 定义支持的照片格式
supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']


# 获取当前脚本文件的绝对路径
script_path = os.path.abspath(__file__)

# 获取当前脚本文件的所在目录的上级目录
directory = os.path.dirname(os.path.dirname(script_path))

# 脚本所在目录的路径下创建程序处理的照片的根文件夹
done_photos_folder = os.path.join(directory, 'done_photos')
os.makedirs(done_photos_folder, exist_ok=True)

# 创建未归类文件夹
unclassified_folder = os.path.join(done_photos_folder, '未归类')
os.makedirs(unclassified_folder, exist_ok=True)


def process_photos(directory_path):
    # 遍历目录中的所有文件和目录
    for filename in os.listdir(directory_path):
        # 构建完整的文件或目录路径
        path = os.path.join(directory_path, filename)

        if os.path.isfile(path):
            # 获取文件的扩展名
            file_ext = os.path.splitext(filename)[1].lower()

            # 如果文件是照片格式,则读取其信息
            if file_ext in supported_formats:
                process_photo(path)

        elif os.path.isdir(path):
            # 处理子目录中的照片
            process_photos(path)


def process_photo(file_path):
    # 如果file_path包含“done_photos”则不处理
    if "done_photos" in file_path or "photo_demo" in file_path:
        return
    # 打开图片
    image = Image.open(file_path)

    # 获取图片的Exif信息
    exif_data = image._getexif()

    # 默认拍摄时间为未归类
    capture_time = "未归类"

    # 遍历Exif信息
    if exif_data:
        for tag_id, value in exif_data.items():
            # 将标签ID转换为标签名
            tag_name = TAGS.get(tag_id, tag_id)
            # 如果标签名为DateTimeOriginal,则将拍摄时间赋值给capture_time
            if tag_name == 'DateTimeOriginal':
                capture_time = value
                break

    print("照片:", file_path)
    print("拍摄时间:", capture_time)

    if capture_time != "未归类":
        # 提取拍摄年份和月份
        year = capture_time[:4]
        month = capture_time[5:7]

        # 创建年份文件夹
        year_folder = os.path.join(done_photos_folder, year)
        os.makedirs(year_folder, exist_ok=True)
        print("创建年份文件夹:", year_folder)

        # 创建月份文件夹
        month_folder = os.path.join(year_folder, year + month)
        os.makedirs(month_folder, exist_ok=True)
        print("创建月份文件夹:", month_folder)

        # 构建最终存放照片的文件路径
        final_path = os.path.join(month_folder, os.path.basename(file_path))
    else:
        # 未归类文件的存放路径
        final_path = os.path.join(unclassified_folder, os.path.basename(file_path))

    try:
        # 复制照片到相应的文件夹中
        shutil.copy2(file_path, final_path)
        print("复制照片到:", final_path)
    except Exception as e:
        print("无法复制照片:", e)

    print()


if __name__ == '__main__':
    process_photos(directory)

或者直接使用python脚本执行也可以。打包文件photo_demo下photo_demo.exe的可执行文件为pyinstaller photo_demo.py命令打包,不含病毒,如果有报毒请自行斟酌。

注意:代码仅做了简单测试,各位客官按需服用
如果是使用photo_demo打包文件执行,会将photo_demo所在目录作为作为扫描起始目录,即扫描该目录下的所有图片,并在该目录下创建:未分类20XX等分类目录。如果是使用脚本的话请自行调试,比如执行目录改为手动指定等

photo_demo打包文件下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1431932.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

西瓜书学习笔记——核化线性降维(公式推导+举例应用)

文章目录 算法介绍实验分析 算法介绍 核化线性降维是一种使用核方法(Kernel Methods)来进行降维的技术。在传统的线性降维方法中,例如主成分分析(PCA)和线性判别分析(LDA),数据被映…

React实例之完善布局菜单(三)

接着上篇的内容继续。规划界面布局。界面分为三个部分,左边为菜单部分,右边上部有个 80 px 高度左右的功能区,下面是主内容区。 依据这个设计,我们进行下面的步骤: 在 SMenu项目中创建一个目录: SLayout, …

解放网工双手-SNMP如何做好运维辅助?

1. SNMP为什么被誉为“网管神器”? 2. SNMP不同版本有何区别? 3. SNMP有哪些问题及Telemetry有何优势? ---- SNMP ----- 简单网络管理协议 U2000:传输设备管理 企业,银行 esight:华为 iMaster NCE-Camp…

【webpack】技巧使用

webpack和TypeScript 安装webpack相关内容安装TS相关内容配置初始化数据初始化运行展示和目录展示报错解决(缺失文件配置) 安装前端必备神奇lodash测试一下entry配置index.html模板配置修改打包出来的index.html的titleinject注入chunks 属性多页面配置 …

从 20 多套 MySQL 到 1 套 TiDB丨骏伯网络综合运营管理平台应用实践

原文来源: https://tidb.net/blog/a38c72a4 本文作者:骏伯网络 唐帆,PingCAP 贺美存 骏伯网络简介 广州骏伯网络是一家以数据驱动的科技公司,聚焦移动互联网营销服务,坚持以客户为中心,深耕 APP、运营…

大数据学习之Redis,十大数据类型的具体应用(四)

3.8 Redis基数统计(HyperLogLog) 需求 统计某个网站的UV、统计某个文章的UV 什么是UV unique Visitor ,独立访客,一般理解为客户端IP 大规模的防止作弊,需要去重复统计独立访客 比如IP同样就认为是同一个客户 需要去…

sqli.labs靶场(29到40关)

29、第二十九关 id1 id1 尝试发现是单引号闭合, -1 union select 1,2,3-- -1 union select 1,2,database()-- -1 union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schemasecurity)-- -1 union select 1,2,(select…

国内最全的Spring Boot系列之七

• 阿里巴巴前高级研发工程师 • 三家千万级互联网企业技术顾问 • MBTI/盖洛普技术专家 • 厦门某高校外聘教师 • 51CTO特约合作讲师 • 网易云课堂签约讲师 •《深入理解设计模式》作者 一转眼马上要过年了,回首2023年,感觉自己无所事事、碌碌无…

python爬虫5

1.selenium交互 无页面浏览器速度更快 #配置好的自己不用管 from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionschrome_options Options()chrome_options.add_argument(‐‐headless)chrome_options.add_argument(‐‐disable‐gpu)# path…

编程效率的跃升之路

编程是一门需要大量的时间和精力投入的技能,提高编程效率则是一个需要不断学习和实践的过程。结合笔者写bug多年的经验,一些学习建议和资源和大家share下。 一、编程如何提效: 熟悉开发工具:掌握常用的开发工具,如集…

flutter抓包绕过

lutter的证书校验 起因: 最近工作上让做个app的复测,把apk发我后,开始尝试挂代理抓包,结果发现抓不到 为是证书没弄好,想着前几天不是刚导入了吗(雾)。又重新导入了下还是不行。然后各种lsp模…

OJ_找位置

题干 代码 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<vector> #include<algorithm> #include<map> using namespace std;int main() {char str[200] { 0 };scanf("%s", str);map<char, vector<int>> times…

ROS入门之通信机制及常用API

文章目录 前言一、话题通信1.话题通信理论2.话题通信常用API&#x1f357;发布者advertisepublish &#x1f356;订阅者subscribe 3.自定义msg 二、服务通信1.服务通信理论2.服务通信常用API&#x1f386;服务端advertiseService &#x1f387;客户端serviceClientros::service…

[大厂实践] Pinterest通用计算平台实践

Pinterest平台团队开发实现了名为PinCompute的高性能通用计算平台&#xff0c;支持Pinterest的大量异构用例和服务。本文介绍了团队在开发这一平台过程中的经验和实践&#xff0c;对于其他平台团队来说&#xff0c;具有很好的参考意义。原文: PinCompute: A Kubernetes Backed …

RabbitMQ面试必备:基本概念、组件原理、消息传递模型,一网打尽。解密高可用性、负载均衡,深入了解安全性配置和性能优化

一、RabbitMQ的基本概念&#xff1a; 1.什么是消息队列&#xff1f; 消息队列是一种在分布式系统中用于在不同组件之间传递消息的通信机制。它允许应用程序和服务通过异步方式进行通信&#xff0c;提高了系统的可伸缩性和松耦合性。消息队列通常包括生产者&#xff08;Produc…

node-sass版本与NodeJS版本不匹配的问题

npm install 报错如下 npm ERR! code 1 npm ERR! path D:\Project\git_Product\YYYY\user\node_modules\node-sass npm ERR! command failed npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c node scripts/build.js 问题原因 node-sass 与 node 版本不匹配 卸载Node…

PM圆桌派:同事不愿意告诉你的职场套路有哪些?

职场是社会的缩影&#xff0c;想要崭露头角&#xff0c;获得更多升职加薪的机会&#xff0c;就不要做着和多数人一样的事情&#xff0c;却期待着不一样的结果。 职场上有很多潜在的规则&#xff0c;要会做事&#xff0c;也要会说话&#xff0c;更要会做人。如果不懂规则&#…

day43_jdbc

今日内容 0 复习昨日 1 SQL注入问题 2 PreparedStatement 3 完成CRUD练习 4 ORM 5 DBUtil (properties) 6 事务操作 0 复习昨日 已经找人提问… 1 SQL注入 1.1 什么是SQL注入 用户输入的数据中有SQL关键词,导致在执行SQL语句时出现一些不正常的情况.这就是SQL注入! 出现SQL注入…

springcloud-gateway升级版本allowedOrigins要改allowedOriginPatterns

前言 报错: java.lang.IllegalArgumentException: When allowCredentials is true,allowedOrigins cannot contain the special value "*"since that cannot be set on the "Access-Control-Allow-Origin"response header. To allow credentials to a se…

AI大模型专题:OWASP大语言模型应用程序十大风险V1.0

今天分享的是AI大模型系列深度研究报告&#xff1a;《AI大模型专题&#xff1a;OWASP大语言模型应用程序十大风险V1.0》。 &#xff08;报告出品方&#xff1a;OWASP&#xff09; 报告共计&#xff1a;14页 LM01:2023_ 提示词注入 描述&#xff1a;提示词注入包括绕过过滤器…