Python腳本批量修復文件時間戳,根據文件名或拍攝日期

實現以下功能

  • 更正文件的 修改時間
  • 批量修改指定文件夾中的特定后綴的文件
  • 根據文件名中的日期修改(優先)
  • 根據 jpg 文件屬性中的拍攝日期修改
  • 根據 mp4 文件屬性中的創建媒體日期修改
  • 模擬運行(Dry Run)模式

依賴

若需要基于jpg文件屬性中的拍攝日期修改,需要python的piexif

pip install piexif

若需要基于mp4文件屬性中的創建媒體日期修改,需要ffmpeg

sudo apt install ffmpge

腳本僅在Linux上進行了測試,若在Windows上運行,可能還需要將ffmpeg的相關目錄加入path。

代碼

fix_timestamp.py

import os
import sys
import re
import piexif
import subprocess
from datetime import datetime, timezone, timedelta
from PIL import Image# 解析命令行參數
if len(sys.argv) < 2:print("[錯誤] 請提供文件夾路徑作為參數。")print("示例: python fix_timestamp.py /home/user/media [--dry-run]")sys.exit(1)folder_path = sys.argv[1]
dry_run = "--dry-run" in sys.argv or "-n" in sys.argv# 要處理的文件后綴
valid_extensions = [".jpg", ".jpeg", ".png", ".mp4"]# 支持的時間格式正則表達式
time_patterns = [# 示例:Screenshot_2018-01-02-18-22-06-934_com.sina.weibo.jpg(r"(\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2})", "%Y-%m-%d-%H-%M-%S"),# 示例:IMG_20230517_094235.jpg(r"(\d{8}_\d{6})", "%Y%m%d_%H%M%S"),# 可以繼續添加其他格式...
]def parse_time_from_filename(filename):"""嘗試從文件名中解析時間"""for pattern, fmt in time_patterns:match = re.search(pattern, filename)if match:try:time_str = match.group(1)dt = datetime.strptime(time_str, fmt)return dtexcept ValueError:continuereturn Nonedef get_jpeg_exif_time(file_path):"""從 JPEG 的 EXIF 中獲取拍攝時間(僅適用于 .jpg/.jpeg)"""try:with Image.open(file_path) as img:if "exif" in img.info:exif_dict = piexif.load(img.info["exif"])if piexif.ExifIFD.DateTimeOriginal in exif_dict["Exif"]:exif_time_str = exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal].decode("utf-8")try:dt = datetime.strptime(exif_time_str, "%Y:%m:%d %H:%M:%S")return dtexcept ValueError:print(f"[錯誤] EXIF時間格式錯誤: {exif_time_str}")except Exception as e:print(f"[異常] 讀取EXIF出錯: {e}")return Nonedef get_mp4_creation_time(file_path):"""使用 ffprobe 獲取 MP4 的 creation_time 元數據"""cmd = ['ffprobe','-v', 'error','-show_entries', 'format_tags=creation_time','-of', 'default=nw=1',file_path]try:result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)output = result.stdout.strip()if output.startswith("TAG:creation_time="):dt_str = output.split("=", 1)[1]try:dt_utc = datetime.fromisoformat(dt_str.replace('Z', '+00:00'))tz_utc_8 = timezone(timedelta(hours=8))dt_local = dt_utc.astimezone(tz_utc_8)return dt_localexcept ValueError as ve:print(f"[解析錯誤] 時間格式不支持: {dt_str}, 錯誤: {ve}")except Exception as e:print(f"[異常] 獲取視頻時間失敗: {e}")return None# 檢查路徑是否存在
if not os.path.isdir(folder_path):print(f"[錯誤] 路徑不存在或不是文件夾: {folder_path}")sys.exit(1)print(f"[信息] 正在處理文件夾: {folder_path}")
if dry_run:print("[信息] 當前為 Dry Run 模式,不會修改任何文件。\n")# 遍歷文件夾中所有指定后綴的文件
for filename in os.listdir(folder_path):ext = os.path.splitext(filename)[1].lower()file_path = os.path.join(folder_path, filename)print(f"\n[處理] 正在處理: {filename}")# 1. 嘗試從文件名中提取時間dt = parse_time_from_filename(filename)if dt:print(f"[成功] 使用文件名中的時間: {dt.strftime('%Y:%m:%d %H:%M:%S')}")else:# 2. 如果是圖片(.jpg/.jpeg),嘗試從 EXIF 獲取時間if ext in [".jpg", ".jpeg"]:dt = get_jpeg_exif_time(file_path)if dt:print(f"[成功] 使用EXIF中的拍攝時間: {dt.strftime('%Y:%m:%d %H:%M:%S')}")else:print(f"[跳過] 沒有可用的EXIF拍攝時間。")# 3. 如果是視頻(.mp4),嘗試從 FFProbe 獲取 creation_timeelif ext == ".mp4":dt = get_mp4_creation_time(file_path)if dt:print(f"[成功] 使用MP4中的創建時間: {dt.strftime('%Y:%m:%d %H:%M:%S')}")else:print(f"[跳過] 沒有可用的creation_time元數據。")else:print(f"[跳過] 當前文件不支持獲取時間信息。")# 如果獲取到了時間,設置文件時間if dt:if dry_run:print(f"[DryRun] [模擬] 將設置文件時間為: {dt.strftime('%Y:%m:%d %H:%M:%S')}(不實際修改)")else:timestamp = dt.timestamp()os.utime(file_path, (timestamp, timestamp))print(f"[完成] 文件時間已更新為: {dt.strftime('%Y:%m:%d %H:%M:%S')}")else:print(f"[跳過] 無法獲取時間信息: {filename}")print("\n>>>>> 運行結束 <<<<<")

運行示例

執行:

sudo python fix_timestamp.py /home/dlw/Media -n  # 模擬運行模式,去掉-n實際運行

輸出:

[處理] 正在處理: 2848404867455998737608616768.mp4
[跳過] 沒有可用的creation_time元數據。
[跳過] 無法獲取時間信息: 2848404867455998737608616768.mp4[處理] 正在處理: 7695642187455636767332932782.mp4
[成功] 使用MP4中的創建時間: 2025:01:03 14:29:21
[DryRun] [模擬] 將設置文件時間為: 2025:01:03 14:29:21(不實際修改)[處理] 正在處理: IMG_20211201_235648_470_5.jpg
[成功] 使用文件名中的時間: 2021:12:01 23:56:48
[DryRun] [模擬] 將設置文件時間為: 2021:12:01 23:56:48(不實際修改)[處理] 正在處理: img-b1b1b00a1589edea0e7c74b235053cd4.jpg
[跳過] 沒有可用的EXIF拍攝時間。
[跳過] 無法獲取時間信息: img-b1b1b00a1589edea0e7c74b235053cd4.jpg[處理] 正在處理: -3cdc6e8e88e57e14.gif
[跳過] 當前文件不支持獲取時間信息。
[跳過] 無法獲取時間信息: -3cdc6e8e88e57e14.gif[處理] 正在處理: 3_d51.png
[跳過] 當前文件不支持獲取時間信息。
[跳過] 無法獲取時間信息: 3_d51.png[處理] 正在處理: IMG551013D.jpg
[成功] 使用EXIF中的拍攝時間: 2025:01:01 00:36:51
[DryRun] [模擬] 將設置文件時間為: 2025:01:01 00:36:51(不實際修改)>>>>> 運行結束 <<<<<

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89145.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89145.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89145.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[Mysql] Connector / C++ 使用

一、Connector / C 使用 要使用 C 語言連接 MySQL&#xff0c;需要使用 MySQL 官網提供的庫&#xff0c;可以去官網進行下載&#xff1a;MySQL :: MySQL Community Downloads 我們使用 C 接口庫來進行連接&#xff0c;要正確使用&#xff0c;還需要做一些準備工作&#xff1a…

【PDF識別改名】使用京東云OCR完成PDF圖片識別改名,根據PDF圖片內容批量改名詳細步驟和解決方案

京東云OCR識別PDF圖片并批量改名解決方案一、應用場景在日常辦公和文檔管理中&#xff0c;經常會遇到大量 PDF 文件需要根據內容進行分類和命名的情況。例如&#xff1a;企業合同管理系統需要根據合同編號、日期等內容自動命名 PDF 文件圖書館數字化項目需要將掃描的圖書章節按…

stm32-modbus-rs485程序移植過程

背景 【modbus學習筆記】Modbus協議解析_modus協議中0.001如何解析-CSDN博客 【Modbus學習筆記】stm32實現Modbus(從機)并移植_stm32 modbus數據處理-CSDN博客 繼上篇成功移植modbus從機例程之后&#xff0c;我要嘗試移植主機的程序。經提醒&#xff0c;可用野火的modbus代碼…

Spring MVC 執行流程詳解:一次請求經歷了什么?

Spring MVC 執行流程詳解&#xff1a;一次請求經歷了什么&#xff1f; 引言 在現代 Web 開發中&#xff0c;Spring MVC 作為 Spring 框架的重要組成部分&#xff0c;廣泛應用于構建靈活、可擴展的 Java Web 應用。作為一個基于 MVC&#xff08;Model-View-Controller&#xff0…

Vue 3的核心機制-解析事件流、DOM更新、數據請求、DOM操作規范及組件庫DOM操作的解決方案

文章目錄概要整體介紹vue 中dom操作推薦方案實例概要 從Vue 3的核心機制出發&#xff0c;結合場景、應用與實例&#xff0c;系統化解析事件流、DOM更新、數據請求、DOM操作規范及組件庫DOM操作的解決方案&#xff1a; 整體介紹 ?? 一、事件流處理機制 核心機制 ? 三個階段…

Python從入門到高手9.2節-Python字典的操作方法

目錄 9.2.1 字典的操作 9.2.2 字典的查找 9.2.3 字典的修改 9.2.4 字典的添加 9.2.5 字典的刪除 9.2.6 今天你逛街了嗎 9.2.1 字典的操作 字典類型是一種抽象數據類型&#xff0c;抽象數據類型定義了數據類型的操作方法&#xff0c;在本節的內容中&#xff0c;教同學們徹…

omniparser v2 本地部署及制作docker鏡像(20250715)

關于 omniparser v2 本地部署&#xff0c;網上資料不算多&#xff0c;尤其是對于土薔內用戶&#xff0c;還是有些坑的。 1、安裝步驟 可參考兩個CSDN博客&#xff1a; &#xff08;1&#xff09;大模型實戰 - ‘OmniParser-V2本地部署安裝 鏈接 &#xff08;2&#xff09;…

自己寫個 `rsync` + `fswatch` 實時增量同步腳本,干掉 Cursor AI、Sublime Text 的SFTP等 插件!

自己寫個 rsync fswatch 實時增量同步腳本&#xff0c;干掉 Cursor AI、Sublime Text 的 SFTP等 插件&#xff01; 作為一個碼農&#xff0c;我最頭疼的事情之一就是編輯器同步代碼到服務器這塊。用過各種各樣的sftp、rsync插件&#xff0c;感覺不好用。。 我琢磨著&#xff1…

linux中at命令的常用用法。

Linux 中 at 命令用于安排一次性定時任務&#xff0c;需要用到在某個時間只需要執行一次的命令的時候&#xff0c;可以使用at 1&#xff1a;安裝at # Debian/Ubuntu sudo apt install at# CentOS/RHEL sudo yum install at2&#xff1a;啟動at sudo systemctl start atd # 啟…

【安卓筆記】RxJava的使用+修改功能+搭配retrofit+RxView防快速點擊

0. 環境&#xff1a; 電腦&#xff1a;Windows10 Android Studio: 2024.3.2 編程語言: Java Gradle version&#xff1a;8.11.1 Compile Sdk Version&#xff1a;35 Java 版本&#xff1a;Java11 1. 介紹RxJava GitHub開源地址&#xff1a;https://github.com/Reactive…

Windows 下原生使用 claude code + Kimi K2

搞定了kimi k2 claude code在windows下原生使用 Windows下使用claude code的障礙是shell環境&#xff08;命令行&#xff09;&#xff0c;非posix風格shell無法正常讓claude code讀取到url和key, 導致無法使用。解決問題的本質是使用符合posix風格的shell環境&#xff0c;我們…

Leetcode Easy題小解(C++語言描述)1

Leetcode Easy題小解&#xff08;C語言描述&#xff09; 相交鏈表 給你兩個單鏈表的頭節點 headA 和 headB &#xff0c;請你找出并返回兩個單鏈表相交的起始節點。如果兩個鏈表不存在相交節點&#xff0c;返回 null 。 圖示兩個鏈表在節點 c1 開始相交**&#xff1a;**題目數據…

EP01:【NLP 第二彈】自然語言處理概述

一、NLP通向智能之路 1.1 圖靈測試 1.1.1 提出背景 由計算機科學家阿蘭?圖靈于 1950 年提出&#xff0c;是早期衡量機器智能水平的重要概念。 1.1.2 提出目的 判斷機器是否能表現出與人類相當的智能行為。 1.1.3 測試原理 場景設定&#xff1a;測試中存在一位人類測試者&#…

Ansible 查看PostgreSQL的版本

Ansible的基礎知識就不說了直接貼劇本- name: Check PostgreSQL versionhosts: db_serversbecome: yesvars:ansible_python_interpreter: /usr/bin/python3db_name: postgresdb_user: postgresdb_password: your_passwordtasks:- name: Install psycopg2ansible.builtin.packag…

【視覺SLAM筆記】第9章 后端1

一、理論1. 狀態估計的概率解釋我們來深入探討一下視覺SLAM中狀態估計的概率解釋。這可以說是理解現代SLAM算法&#xff08;尤其是后端優化&#xff09;的基石1. 問題的核心&#xff1a;不確定性SLAM&#xff08;同步定位與建圖&#xff09;的本質是在一個未知環境中&#xff0…

(數據結構)復雜度

基本概念說明 數據結構 定義&#xff1a;數據結構(Data Structure)是計算機存儲、組織數據的方式&#xff0c;指相互之間存在?種或多種特定關系的數據元素的集合。沒有?種單?的數據結構對所有用途都有用&#xff08;要考慮適配、效率問題&#xff0c;在不同情況下使用合適的…

玩轉Docker | 使用Docker部署bender個人導航頁工具

玩轉Docker | 使用Docker部署bender個人導航頁工具 前言 一、bender介紹 Bender 簡介 Bender 的主要特點 二、系統要求 環境要求 環境檢查 Docker版本檢查 檢查操作系統版本 三、部署bender服務 下載bender鏡像 編輯部署文件 創建容器 檢查容器狀態 檢查服務端口 安全設置 四、…

解決了困擾我的upload靶場無法解析phtml等后綴的問題

本文章為解決困擾我的 upload 靶場無法解析 phtml 問題 ? 這個問題直接讓我過不了Upload-Pass-03這一關&#xff0c;一直卡著。 ? 痛太痛了 &#xff0c;為什么無法解析上傳之后的 phtml 后綴文件&#xff01;這塊兒折磨了博主一天多&#xff0c;太不容易了&#xff0c;查找…

Leetcode百題斬-二分搜索

二分搜索也是一個很有趣的專題&#xff0c;被做過的題中&#xff0c;剛好一個Easy&#xff0c;一個Medium和一個Hard&#xff0c;剛好可以看看&#xff0c;二分搜索的三個難度等級都是啥樣的。 124. Binary Tree Maximum Path Sum[Hard]&#xff08;詳見二叉樹專題&#xff09;…

【IDEA】格式化代碼工具配置

格式化代碼快捷鍵&#xff1a; CtrlAltL格式代碼的時候不會再方法名與參數中間添加空格默認不勾選的情況下&#xff1a;代碼樣例&#xff1a;勾選之后的樣例&#xff1a;選擇不勾選&#xff0c;IDEA默認情況下就是不勾選的狀態忽略加載文件有些非必要加載到開發工具中的文件我們…