当前位置: 首页 > article >正文

Python 文件批量处理:重命名/备份/同步运维实战指南

老王在一家小公司管服务器。每天最烦的事就是开发同事丢来一堆日志文件文件名乱七八糟——有的叫log1.txt有的叫1212.log还有的直接叫新建文本文档(1).log。更糟的是每周五要手动备份一遍配置文件还得确保备份目录和源目录同步。老王决定写几个Python脚本把这些破事自动化。场景一批量重命名——让文件名规规矩矩先拿日志文件开刀。老王想把所有.log文件改成2024-12-01_001.log这种格式按修改时间排序。import os from datetime import datetime def rename_logs(folder_path): log_files [f for f in os.listdir(folder_path) if f.endswith(.log)] for index, filename in enumerate(log_files, 1): old_path os.path.join(folder_path, filename) # 获取修改时间 mtime os.path.getmtime(old_path) date_str datetime.fromtimestamp(mtime).strftime(%Y-%m-%d) new_name f{date_str}_{index:03d}.log new_path os.path.join(folder_path, new_name) os.rename(old_path, new_path) print(f{filename} - {new_name}) rename_logs(/var/logs)运行一次新建文本文档(1).log变成了2024-12-15_005.log一目了然。但os.rename有个坑目标文件已存在时会报错。加上覆盖检查更稳妥def safe_rename(old_path, new_path): if os.path.exists(new_path): base, ext os.path.splitext(new_path) counter 1 while os.path.exists(f{base}_{counter}{ext}): counter 1 new_path f{base}_{counter}{ext} os.rename(old_path, new_path) return new_path更灵活的模式匹配用glob模块按规则筛选文件比如只改report_*.xlsximport glob for filepath in glob.glob(/data/report_*.xlsx): dirname, filename os.path.split(filepath) # 提取月份比如 report_202412.xlsx - 202412 month filename.split(_)[1].split(.)[0] new_name f财务报告_{month}.xlsx os.rename(filepath, os.path.join(dirname, new_name))正则表达式批量替换某些文件命名有规律但混乱比如IMG_001 (1).jpg、IMG_001 (2).jpg这种括号空格让人头疼。import re def clean_filenames(folder, pattern, replacement): for filename in os.listdir(folder): new_name re.sub(pattern, replacement, filename) if new_name ! filename: old_path os.path.join(folder, filename) new_path os.path.join(folder, new_name) os.rename(old_path, new_path) print(f修正: {filename} - {new_name}) # 去掉文件名中的空格和括号 clean_filenames(./photos, r[\(\s\)], ) # IMG_001 (1).jpg - IMG_0011.jpg 虽然不太完美但至少没空格了场景二智能备份——别每次都全量复制老王之前用cp -r全量备份几十G的配置文件越来越慢。他需要增量备份——只复制改动过的文件。import shutil import hashlib def md5_file(filepath): 计算文件MD5用于判断内容是否变化 hash_md5 hashlib.md5() with open(filepath, rb) as f: for chunk in iter(lambda: f.read(4096), b): hash_md5.update(chunk) return hash_md5.hexdigest() def incremental_backup(src_dir, dst_dir, state_filebackup_state.json): import json # 加载上次备份的状态 if os.path.exists(state_file): with open(state_file, r) as f: last_state json.load(f) else: last_state {} new_state {} copied_count 0 for root, dirs, files in os.walk(src_dir): rel_path os.path.relpath(root, src_dir) dst_root os.path.join(dst_dir, rel_path) os.makedirs(dst_root, exist_okTrue) for file in files: src_file os.path.join(root, file) dst_file os.path.join(dst_root, file) file_md5 md5_file(src_file) file_key os.path.relpath(src_file, src_dir) new_state[file_key] file_md5 # 检查是否需要备份 if file_key not in last_state or last_state[file_key] ! file_md5: shutil.copy2(src_file, dst_file) # copy2保留元数据 copied_count 1 print(f备份: {file_key}) # 保存新状态 with open(state_file, w) as f: json.dump(new_state, f, indent2) print(f完成共备份 {copied_count} 个文件) incremental_backup(/etc/nginx, /backup/nginx)第一次运行会全量备份第二次只复制改动过的文件。状态文件backup_state.json记录了每个文件的MD5拿掉它就能强制全量。定时自动备份结合schedule库设置每天凌晨2点执行。import schedule import time def auto_backup_job(): print(f{datetime.now()} 开始自动备份) incremental_backup(/data/mysql, /backup/mysql) print(备份完成) schedule.every().day.at(02:00).do(auto_backup_job) while True: schedule.run_pending() time.sleep(60)场景三目录同步——像rsync一样工作老王还负责维护两台服务器之间的文件同步。rsync很好用但某些环境不允许装额外软件自己写一个轻量版。import filecmp import shutil def sync_dirs(src, dst, delete_extraFalse): 同步目录dst会变成和src一模一样 delete_extraTrue时删除dst中多余的文件 if not os.path.exists(dst): os.makedirs(dst) # 比较两个目录 comparison filecmp.dircmp(src, dst) # 复制src有但dst没有的 for file in comparison.left_only: src_path os.path.join(src, file) dst_path os.path.join(dst, file) if os.path.isdir(src_path): shutil.copytree(src_path, dst_path) else: shutil.copy2(src_path, dst_path) print(f新增: {file}) # 复制有更新的 for file in comparison.diff_files: src_path os.path.join(src, file) dst_path os.path.join(dst, file) shutil.copy2(src_path, dst_path) print(f更新: {file}) # 删除dst多余的 if delete_extra: for file in comparison.right_only: dst_path os.path.join(dst, file) if os.path.isdir(dst_path): shutil.rmtree(dst_path) else: os.remove(dst_path) print(f删除: {file}) # 递归处理子目录 for common_dir in comparison.common_dirs: sync_dirs( os.path.join(src, common_dir), os.path.join(dst, common_dir), delete_extra ) sync_dirs(/home/user/project, /backup/project, delete_extraTrue)filecmp.dircmp一次性告诉你三类差异left_only源独有、right_only目标独有、diff_files内容不同。递归调用就能同步整个目录树。实时同步监听文件系统事件文件一改动立刻同步。from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler class SyncHandler(FileSystemEventHandler): def __init__(self, src, dst): self.src src self.dst dst def on_modified(self, event): if not event.is_directory: rel_path os.path.relpath(event.src_path, self.src) dst_path os.path.join(self.dst, rel_path) os.makedirs(os.path.dirname(dst_path), exist_okTrue) shutil.copy2(event.src_path, dst_path) print(f实时同步: {rel_path}) observer Observer() handler SyncHandler(/watch/src, /watch/dst) observer.schedule(handler, /watch/src, recursiveTrue) observer.start()运行后在/watch/src里新建或修改任何文件都会瞬间复制到/watch/dst。适合配置文件热同步场景。场景四批量清理旧文件日志文件占满磁盘是家常便饭。写个脚本自动删除30天前的文件。import time def clean_old_files(folder, days30, pattern*): now time.time() cutoff now - (days * 86400) for root, dirs, files in os.walk(folder): for file in files: if not glob.fnmatch.fnmatch(file, pattern): continue filepath os.path.join(root, file) mtime os.path.getmtime(filepath) if mtime cutoff: os.remove(filepath) print(f删除旧文件: {filepath} ({datetime.fromtimestamp(mtime).date()})) # 删除空目录 for dir in dirs: dirpath os.path.join(root, dir) try: os.rmdir(dirpath) print(f删除空目录: {dirpath}) except OSError: pass clean_old_files(/var/log/nginx, days7, pattern*.log*)更安全的干跑模式先预览不执行确认无误再真正删除。def dry_run_clean(folder, days30): now time.time() cutoff now - (days * 86400) to_delete [] for root, dirs, files in os.walk(folder): for file in files: filepath os.path.join(root, file) if os.path.getmtime(filepath) cutoff: to_delete.append(filepath) print(f将删除 {len(to_delete)} 个文件:) for path in to_delete[:10]: # 只显示前10个 print(f {path}) if input(确认删除(y/n): ).lower() y: for path in to_delete: os.remove(path) print(删除完成)踩坑与进阶技巧文件名编码问题Windows和Linux的文件名编码不同。跨平台时用os.fsencode和os.fsdecode处理。def safe_listdir(path): try: return os.listdir(path) except UnicodeEncodeError: return [os.fsdecode(f) for f in os.listdir(os.fsencode(path))]大量文件性能优化os.listdir在几十万文件的目录里很慢用scandir代替。with os.scandir(/big_folder) as entries: for entry in entries: if entry.is_file() and entry.name.endswith(.log): print(entry.name, entry.stat().st_size)scandir一次性返回文件属性避免额外调用stat速度提升2-5倍。移动而不是复制备份到同一磁盘时移动文件比复制快得多。def move_to_archive(src, dst): os.makedirs(dst, exist_okTrue) for filename in os.listdir(src): shutil.move(os.path.join(src, filename), os.path.join(dst, filename))日志记录所有操作记下来出问题能追溯。import logging logging.basicConfig( filenamefile_ops.log, levellogging.INFO, format%(asctime)s - %(message)s ) def log_op(op, src, dstNone): msg f{op}: {src} if dst: msg f - {dst} logging.info(msg) print(msg)一键搞定综合运维脚本把常用功能打包成命令行工具import argparse def main(): parser argparse.ArgumentParser(description文件批量处理工具) subparsers parser.add_subparsers(destcommand) rename_parser subparsers.add_parser(rename) rename_parser.add_argument(folder) rename_parser.add_argument(--pattern, default*) rename_parser.add_argument(--template, default{date}_{index}) backup_parser subparsers.add_parser(backup) backup_parser.add_argument(src) backup_parser.add_argument(dst) backup_parser.add_argument(--incremental, actionstore_true) sync_parser subparsers.add_parser(sync) sync_parser.add_argument(src) sync_parser.add_argument(dst) sync_parser.add_argument(--delete, actionstore_true) clean_parser subparsers.add_parser(clean) clean_parser.add_argument(folder) clean_parser.add_argument(--days, typeint, default30) args parser.parse_args() if args.command rename: rename_files(args.folder, args.pattern, args.template) elif args.command backup: if args.incremental: incremental_backup(args.src, args.dst) else: shutil.copytree(args.src, args.dst) elif args.command sync: sync_dirs(args.src, args.dst, args.delete) elif args.command clean: clean_old_files(args.folder, args.days) # 使用示例 # python file_tool.py rename ./logs --pattern *.log --template {date}_{index} # python file_tool.py backup /data /backup --incremental # python file_tool.py sync /project /backup/project --delete老王把这些脚本整合起来设置好定时任务。现在每天早上一到公司检查一下日志文件有没有按规范命名备份有没有成功同步。之前每周五加班备份的日子一去不返他泡杯茶就能开始一天的工作。

相关文章:

Python 文件批量处理:重命名/备份/同步运维实战指南

老王在一家小公司管服务器。每天最烦的事,就是开发同事丢来一堆日志文件,文件名乱七八糟——有的叫log1.txt,有的叫1212.log,还有的直接叫新建文本文档(1).log。更糟的是,每周五要手动备份一遍配置文件,还得…...

【进阶篇】2.3 五分钟掌握Redis HyperLogLog 实战场景与性能调优

1. HyperLogLog 五分钟快速入门 第一次接触HyperLogLog时,我也被这个奇怪的名字吸引了注意力。这到底是什么神奇的数据结构?简单来说,它就是Redis提供的一个"计数器",但和我们熟悉的普通计数器完全不同。想象一下&#…...

Vue Router 嵌套路由的“斜杠”法则与路径设计避坑指南

Vue Router 嵌套路由的“斜杠”法则与路径设计避坑指南 在构建现代化的单页面应用(SPA)时,Vue Router 是事实上的路由标准。它强大而灵活,但其中一个细节——嵌套路由中路径(path)前的斜杠(/&am…...

ExplorerPatcher终极指南:5分钟让Windows 11变回熟悉的老朋友

ExplorerPatcher终极指南:5分钟让Windows 11变回熟悉的老朋友 【免费下载链接】ExplorerPatcher This project aims to enhance the working environment on Windows 项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher 你是不是也和我一样&…...

终极指南:如何使用League Akari英雄联盟工具实现游戏体验全面优化

终极指南:如何使用League Akari英雄联盟工具实现游戏体验全面优化 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 您是否厌倦了在英…...

从科幻小说到产品设计:如何用‘What-If’思维模型,提前5年预判技术趋势

科幻思维解码:用未来叙事重构产品创新逻辑 当科幻遇见产品:一场跨越时空的思维实验 1982年上映的《银翼杀手》描绘了2019年的洛杉矶街头全息广告与仿生人共存的世界,这个曾被视作天方夜谭的设定,如今在增强现实技术和人形机器人领…...

CCMusic可复现性保障:Dockerfile+requirements.txt+config.yaml三件套详解

CCMusic可复现性保障:Dockerfilerequirements.txtconfig.yaml三件套详解 1. 项目概述 CCMusic Audio Genre Classification Dashboard是一个基于Streamlit和PyTorch构建的高级音频分析平台。这个项目的独特之处在于它不采用传统的音频特征提取方法,而是…...

专业指南:如何快速重置Navicat Premium的macOS试用期

专业指南:如何快速重置Navicat Premium的macOS试用期 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac 对于数据库开…...

别再用默认对齐了!C语言__attribute__((packed/aligned))实战避坑,手把手教你优化嵌入式内存布局

别再用默认对齐了!C语言__attribute__((packed/aligned))实战避坑指南 在嵌入式开发中,内存资源往往捉襟见肘。一个结构体多占几个字节,可能就意味着系统无法运行。但你是否知道,编译器默认的对齐规则可能正在悄悄浪费你宝贵的内存…...

企业级跨平台UI开发实战:深度解析Semi.Avalonia主题库的设计哲学与技术实现

企业级跨平台UI开发实战:深度解析Semi.Avalonia主题库的设计哲学与技术实现 【免费下载链接】Semi.Avalonia Avalonia theme inspired by Semi Design 项目地址: https://gitcode.com/gh_mirrors/se/Semi.Avalonia 在当今多平台应用开发的时代,开…...

如何快速使用RPGMakerDecrypter:解密RPG Maker加密资源的完整指南

如何快速使用RPGMakerDecrypter:解密RPG Maker加密资源的完整指南 【免费下载链接】RPGMakerDecrypter Tool for decrypting and extracting RPG Maker XP, VX and VX Ace encrypted archives and MV and MZ encrypted files. 项目地址: https://gitcode.com/gh_m…...

告别官方Demo!用ESP32-CAM+Arduino IDE打造稳定人脸识别门禁(含SD卡存储避坑指南)

ESP32-CAM人脸识别门禁实战:从Flash崩溃到SD卡稳定存储的完整方案 当你在深夜调试ESP32-CAM人脸识别项目时,突然发现辛苦录入的20组人脸数据在重启后全部消失——这种崩溃体验我太熟悉了。官方Demo的Flash存储方案就像个定时炸弹,而本文将带你…...

差评管理不是伪需求:餐饮店最容易被忽视的一笔小生意

我是小杨,9年 Java 后端。 主业写系统,副业专门研究普通人今天就能开干的赚钱项目。 这个专栏只做一件事: 把一个赚钱思路,拆到你今天就能开始。 没有空话,只有4样东西: 我的判断 落地步骤 真实数据 踩坑记录 差评管理不是伪需求:餐饮店最容易被忽视的一笔小生意** 评…...

如何一键同步网易云音乐到Discord?完整免费教程指南

如何一键同步网易云音乐到Discord?完整免费教程指南 【免费下载链接】NetEase-Cloud-Music-DiscordRPC 在Discord上显示网抑云/QQ音乐. Enables Discord Rich Presence For Netease Cloud Music/Tencent QQ Music. 项目地址: https://gitcode.com/gh_mirrors/ne/…...

级联双二阶IIR滤波器设计与实现详解

1. 从零理解级联双二阶IIR滤波器设计在数字信号处理领域,IIR(无限脉冲响应)滤波器因其高效的频率选择特性而广受欢迎。但高阶IIR滤波器直接实现时,系数量化误差会导致严重的稳定性问题。级联双二阶(Biquad)…...

别再手动改参数了!Simulink模型参数初始化的3种高效方法(附InitFcn回调函数实战)

别再手动改参数了!Simulink模型参数初始化的3种高效方法(附InitFcn回调函数实战) 在复杂的Simulink模型开发中,参数初始化往往是工程师们最头疼的环节之一。想象一下这样的场景:你正在调试一个包含数十个滤波器的通信系…...

Nginx反向代理SSE长连接:配置优化与性能调优实战

1. 为什么需要Nginx反向代理SSE长连接 最近在做一个实时数据监控项目时,遇到了一个棘手的问题:当有大量客户端同时连接SSE服务时,后端服务器直接崩溃了。这让我意识到,像SSE这样的长连接服务,如果没有合适的代理层做缓…...

3分钟搞定B站视频下载:BiliDownloader终极免费解决方案

3分钟搞定B站视频下载:BiliDownloader终极免费解决方案 【免费下载链接】BiliDownloader BiliDownloader是一款界面精简,操作简单且高速下载的b站下载器 项目地址: https://gitcode.com/gh_mirrors/bi/BiliDownloader 还在为无法下载B站视频而烦恼…...

AS2785 AC输入50-260V或DC输入20-450V 电流10mA,输出2.7V/3.3V/5V

1、方案名称:AS2785 AC输入50-260V或DC输入20-450V 电流10mA,输出2.7V/3.3V/5V2、品牌:紫源微(Zymicro)3、描述:AS2785是一款高性能线性稳压器,提供高达450V DC的非常宽的工作输入电压范围&…...

Bebas Neue字体终极指南:从快速安装到专业应用

Bebas Neue字体终极指南:从快速安装到专业应用 【免费下载链接】Bebas-Neue Bebas Neue font 项目地址: https://gitcode.com/gh_mirrors/be/Bebas-Neue Bebas Neue字体是全球最受欢迎的几何无衬线字体之一,这款开源字体以其简洁现代的设计语言和…...

跨平台资源下载神器:5分钟掌握多平台内容批量获取技巧

跨平台资源下载神器:5分钟掌握多平台内容批量获取技巧 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 在数字内容…...

原神模型导入终极指南:GIMI工具完整使用教程

原神模型导入终极指南:GIMI工具完整使用教程 【免费下载链接】GI-Model-Importer Tools and instructions for importing custom models into a certain anime game 项目地址: https://gitcode.com/gh_mirrors/gi/GI-Model-Importer 想要为《原神》角色打造独…...

解锁C语言中的多返回值技巧

在C语言编程中,常常会遇到需要从函数中返回多个值的情况。虽然C语言不直接支持多返回值,但我们可以通过一些技巧来实现这一目的。本文将详细探讨如何在C语言中返回多个值,并通过实例说明。 一、背景介绍 在C语言中,函数默认只能返回一个值。这对于需要处理多个结果的情况…...

ANSYS Workbench新手避坑:用BEAM188单元模拟工字钢悬臂梁,从建模到后处理完整流程

ANSYS Workbench新手避坑:用BEAM188单元模拟工字钢悬臂梁,从建模到后处理完整流程 工字钢悬臂梁在工程实践中极为常见,从建筑阳台到机械臂设计,这种结构几乎无处不在。对于刚接触有限元分析的工程师或学生来说,如何在A…...

避开Fluent计算崩溃:用这3种网格划分策略彻底解决floating error问题

避开Fluent计算崩溃:3种网格划分策略彻底解决floating error问题 在CFD仿真工程师的日常工作中,没有什么比看到"floating point error"这个报错更令人沮丧的了。这个看似简单的错误提示背后,往往隐藏着复杂的数值计算问题。根据我们…...

Jetson Nano上MediaPipe GPU加速实战:从编译到部署,让你的AI应用帧率翻倍

Jetson Nano上MediaPipe GPU加速实战:从编译到部署,让你的AI应用帧率翻倍 在嵌入式AI领域,Jetson Nano凭借其出色的GPU性能成为众多开发者的首选平台。然而,当我们将Google的MediaPipe框架部署到这块开发板上时,默认的…...

【豆包从入门到精通共10篇】007、多模态应用:图像理解与生成能力探索

007、多模态应用:图像理解与生成能力探索 从一次深夜调试说起 上周三凌晨两点,我被测试组的紧急电话叫醒:“你们那个图像描述接口,传了张电路板照片,返回的结果是‘一只猫在玩毛线球’。” 我瞬间清醒——这问题可太致命了。我们的模型在标准数据集上准确率明明有92%,怎…...

别再死记OSPF网络类型了!通过一个跨网段实验,彻底搞懂P2P和Broadcast的区别

从实验视角拆解OSPF网络类型:P2P与Broadcast的本质差异 在准备CCNA/CCNP认证的过程中,OSPF网络类型总是一个让人头疼的知识点。许多学习者习惯性地死记硬背各种类型的特性,却很少思考它们在实际网络中的行为差异。今天,我们将通过…...

Navicat重置试用期终极指南:3种方法彻底解决14天限制

Navicat重置试用期终极指南:3种方法彻底解决14天限制 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac 还在为Navic…...

数字信号处理:FIR与IIR滤波器原理与应用指南

1. 离散时间滤波器基础概念离散时间滤波器是数字信号处理系统的核心构建模块,它将输入序列通过数学运算转换为输出序列。从数学角度看,线性时不变(LTI)滤波器可以完全由常系数差分方程描述。这类系统具有两个关键特性:线性性:系统…...