Python工具-清理Unity(批量深度)清理U3D项目工程保留关键工程文件

前沿

1. Unity工程越来越多,很久不用的工程里存在了很多无用的大文件夹,极大的影响电脑容量。
2. 我电脑里面U3D工程只有17个,但容量就高达60GB,使用自己编写的工具清理后,减到了30GB多。清理了不是很重要的文件和文件夹,保留了关键的工程文件。这样减少了电脑的容量,又保证Unity工程的不损坏。当然这个清理工具是针对很久不用的一些工程。
3. 在清理你的文件时,不会直接对其进行删除,而是放到回收站。 所以防止删除了你自定义的其他文件,建议运行程序后,请打开回收站,稍微过一遍,看一下是否有重要的文件,有的话还是需要还原的。
4. 关于如何使用,请百度怎么运行Python文件。


代码以及关键功能

  1. Print颜色化输出
  2. 自动获取脚本当前目标,判断是原python还是打包后的文件。防止删除的时候把自己也删除了。
  3. 自动对输入的根目录进行判断,可以对绝对路径,自身路径,自身路径的子目录进行检查。
  4. 自动简化路径长度,让Print输出正常。但同时会减少文件夹的可识别性。
  5. 可以检查脚本所在的文件夹,也可以处理子目录,默认子目录递归深度最深为5层,可以自己调节这个参数。

关键的字段
- root_path (str): 需要遍历的根目录,不能太浅,否则容易误删除文件
- target_folders (list): 目标文件夹,尽量多并且准,不然也容易雷同被删除
- protected_items (list): 删除的时候,需要保护的文件夹,或者文件
- protected_extensions (list): 对于一些有很多相同后缀的文件进行保护
- max_depth (int): 程序遍历文件夹的最大深度,默认为5

import sys
import os
from send2trash import send2trash# 定义颜色代码
WHITE = "\033[97m"
RED = "\033[91m"
YELLOW = "\033[93m"
RESET = "\033[0m"def get_program_path():# 检查程序是否被打包if getattr(sys, 'frozen', False):# 程序被打包,使用 sys.executable 获取可执行文件路径program_path = sys.executableelse:# 程序未被打包,使用 __file__ 获取当前脚本路径program_path = os.path.abspath(__file__)return program_path# 获取自身文件名
ScriptPath = get_program_path()
ScriptName = os.path.basename(ScriptPath)"""
Parameters:- root_path (str): 需要遍历的根目录,不能太浅,否则容易误删除文件- target_folders (list): 目标文件夹,尽量多并且准,不然也容易雷同被删除- protected_items (list): 删除的时候,需要保护的文件夹,或者文件- protected_extensions (list): 对于一些有很多相同后缀的文件进行保护- max_depth (int): 程序遍历文件夹的最大深度,默认为5
"""
def main():print("----------------------------------------------------------------")print(ScriptName + " 开始处理文件")#需要遍历的根目录root_path = '.' #你的目录前需要加‘r’,比如 r"F:\UnityProjects"  #目标文件夹名称,对于Unity来说 "Assets"、"ProjectSettings" 和 "Packages" 是项目中最重要的文件target_folders = ["Assets","Packages","ProjectSettings"] #["a","b","c"] #需要被保护不被删除的文件或文件夹protected_items = ["Others","Python","config","UserSettings","Configs","LICENSE","user.keystore","素材","密钥",'.gitignore','.git','Server']#对于特定的后缀,直接会防止删除protected_extensions = ['.config','.htm','.txt','.gitignore','.git','.xlsx','.unitypackage', '.md', '.py', '.keystore','.jpg','.png','.jpeg','.mp4']protected_items.append(ScriptName)#校验根目录root_path = validate_and_adjust_root_path(root_path)find_and_clean_directories(root_path,target_folders,protected_items,protected_extensions)print("处理文件完成")print("----------------------------------------------------------")#识别根目录有效性并且对其进行校验
def validate_and_adjust_root_path(root_path):# 如果有效则直接返回if root_path and os.path.isdir(root_path):return root_path# 获取当前脚本所在目录self_path = os.path.dirname(ScriptPath)# 尝试将传入的 root_path 与当前脚本所在目录结合adjusted_root_path = os.path.join(self_path, root_path) if root_path else self_path# 如果组合后的路径是有效的目录,则返回该路径,否则返回当前脚本所在目录if os.path.isdir(adjusted_root_path):return adjusted_root_pathreturn self_pathSimplifyPath = {}
#对路径进行简化,隐藏过多的上级目录
def simplify_path(path, max_levels=3):global SimplifyPath  # 检查路径是否已经被处理过if path in SimplifyPath:return SimplifyPath[path]# 自动检测系统的路径分隔符sep = os.path.sep# 将路径分割成单独的部分parts = path.split(sep)# 如果路径部分多于max_levels,则进行简化if len(parts) > max_levels + 1:  # 加1是因为分割后第一个元素可能是空字符串(对于绝对路径)# 用".."替换多余的级别,并保留最后max_levels个级别simplified_parts = ['..'] * (len(parts) - max_levels - 1) + parts[-max_levels:]# 重新组合路径simplified_path = sep.join(simplified_parts)# 将处理结果存储在字典中SimplifyPath[path] = simplified_pathreturn simplified_pathelse:# 如果路径级别不多于max_levels,不做改变直接返回,并将结果存储在字典中#SimplifyPath[path] = pathreturn pathTotal_DelectNumber = 1
def find_and_clean_directories(root_path, target_folders, protected_items,protected_extensions, max_depth=5):#检查当前目录是否包含目标文件夹。有则进行放入回收站操作def is_match_and_clean(dir_path):global Total_DelectNumber  contents = set(item.strip().lower() for item in os.listdir(dir_path))  # 将目录内容转换为小写targets = set(folder.strip().lower() for folder in target_folders)protected = set(item.strip().lower() for item in protected_items)# 检查当前目录中是否存在所有的目标文件夹(不区分大小写)if targets.issubset(contents):print(YELLOW+"第{0}轮回收准备:确定匹配的目录:{1}".format(Total_DelectNumber,simplify_path(dir_path))+RESET)# 通过删除所有非目标、非受保护的文件来清理目录trash_number = 0is_clean= Falsefor item in contents:original_item = next((orig for orig in os.listdir(dir_path) if orig.strip().lower() == item), None)if original_item and original_item.strip().lower() not in targets and original_item.strip().lower() not in protected:item_path = os.path.join(dir_path, original_item)#检查文件后缀是否否和标准_, ext = os.path.splitext(original_item)if not ext.lower() in protected_extensions:if os.path.isdir(item_path) or os.path.isfile(item_path):print(RED+"即将删除:" + simplify_path(item_path)+RESET)  # 增强日志输出send2trash(item_path)trash_number += 1is_clean = Trueif is_clean : print(YELLOW+"2. 清理了{0}个文件 - 目录:{1}".format(trash_number,simplify_path(dir_path))+RESET)print(YELLOW+"-----总共清理了{0}个工程-----".format(Total_DelectNumber)+RESET)Total_DelectNumber += 1else: print(YELLOW+"3. 已经是干净的目录了:{0}".format(simplify_path(dir_path))+RESET)return Truereturn False#检查执行中的目录里面是否匹配条件,并进行匹配则回收def traverse_and_clean(dir_path, current_depth=1):if current_depth >= max_depth:return# 首先检查当前目录(dir_path)本身是否满足条件if is_match_and_clean(dir_path):returncleaned = Falsefull_path = ""for entry in os.listdir(dir_path):full_path = os.path.join(dir_path, entry)if os.path.isdir(full_path):print("检查目录:{0}".format(simplify_path(full_path)))# Check and clean the current directory if it's a matchif is_match_and_clean(full_path):cleaned = Truecontinue  # break | Stop searching this level once a match is found and cleanedelse:# Recursively traverse the subdirectorytraverse_and_clean(full_path, current_depth + 1)if cleaned:# 如果对此目录进行清理了,则跳过这个级别的剩余目录returntraverse_and_clean(root_path)# find_and_clean_directories("/path/to/root", ["A", "B", "C"], ["D", "E.txt"])main()

效果展示

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

【CTA动画】制作全记录 笔记

3Dxchange的使用 让图片跳舞 导入:I:\安装包\#动画开发\test\跳舞 model(includeTPose).fbx 转成非标准角色 手动点击骨骼,然后点击人物骨骼,选择00_t-pose 绿灯了就可以转换了,记得启用。 上面的自定义可以先选择3DS 转换后…

Java数据结构-顺序表

目录 1. 顺序表的相关概念1.1 线性表1.2 顺序表2. 功能实现2.1 整体框架2.2 乱七八糟的功能(bushi)2.2.1 判断容量是否满2.2.2 返回顺序表当前长度2.2.3 扩容2.2.4 清空整个顺序表 2.3 插入数据2.3.1 头插数据2.3.2 尾插数据2.3.3 指定位置插入 2.4 删除数据2.4.1 删除第一次出…

微服务之Nacos配置管理

文章目录 前言一、统一配置管理Nacos操作二、统一配置管理java操作1.引入依赖2.创建配置文件3.测试4.总结 三、Nacos配置自动更新1.添加注解RefreshScope2.使用ConfigurationProperties注解3.总结 四、Nacos多环境配置共享1.配置文件2.多种配置的优先级3.总结 总结 前言 一、统…

leetcode 150.逆波兰表达式求值

题目 思路 逆波兰表达式也是经典的栈的应用问题。 先说什么是逆波兰表达式(也叫后缀表达式) 我们习惯的是这样的表达式:1 2 / 3 ,这也叫中缀表达式。 但是对于计算机来说不好理解,当从左扫描到 2 的时候还需要再判断2后面是什…

STM32 | Systick定时器(第四天源码解析)

STM32 | Systick定时器(第四天)STM32 | STM32F407ZE中断、按键、灯(续第三天)1、参考delay_us代码,完成delay_ms的程序 定时器频率换算单位:1GHZ=1000MHZ=1000 000KHZ = 1000 000 000HZ 定时器定时时间:计数个数/f(频率) 或者 (1/f(频率))*计数的个数 500/1MHZ = 500/1…

C++面向对象三大特征-----继承(详细版)

目录 继承 一、继承的基础介绍 普通版网页和继承版网页的区别 语法 二、继承方式 三种继承方式 三、继承中的对象模型 四、继承中构造和析构函数 五、继承同名成员的处理方式 访问同名成员: 作用域写法: 六、继承同名静态成员的处理方式 访问…

Qt播放音乐代码示例

主界面 点击play按钮播放或暂停音乐,拖动进度条,音乐对应播放。 QWidget window;QPushButton* playButton new QPushButton("Play");// Qt 播放音乐// 创建 QMediaPlayer 对象QMediaPlayer* player new QMediaPlayer;// 指定音频文件的路径…

MySQL B+树索引 和 Redis 中跳表索引的区别

一、MySQL B树索引 和 Redis 中跳表索引 在 MySQL 中常用的索引是 B树索引,而 Redis 中,例如 zset 使用的的是跳表索引,两者有什么区别呢,MySQL 为什么不使用 跳表 呢?或者说 Redis 中为什么不使用 B树 呢&#xff1f…

章节10实验--Ubuntu18.04 Qt MySQL libqsqlmysql.so

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容,所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者:房胜、李旭健、黄…

golang 对接第三方接口 RSA 做签(加密) 验签(解密)

一、过程 1.调用第三方接口前,一般需要按规则将参数按key1value1&key2value2 阿斯克码排序,sign参数不参与加密 2.将排序并连接好的参数字符串通过我方的私钥证书(.pem)进行加密得到加密串,当然加密得到的是 []byte 字节流&…

看完就等于拿捏浮点数在内存中的储存了

诸君又该学习了,今天我们继续来一睹浮点数的奥妙真容。 经过前面文章对整形提升相关的解释,我们都对整形和字符在内存空间上的储存已经有了大概的认知,那么现在我们就来好好讲讲浮点数在内存中的储存规则。 目录 浮点数与整形储存的不同 …

41-Vue-webpack基础

webpack基础 前言什么是webpackwebpack的基本使用指定webpack的entry和output 前言 本篇开始来学习下webpack的使用 什么是webpack webpack: 是前端项目工程化的具体解决方案。 主要功能:它提供了友好的前端模块化开发支持,以及代码压缩混淆、处理浏览…

自定义序列化

3.2.2.自定义序列化 RedisTemplate可以接收任意Object作为值写入Redis: 只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的: 缺点: 可读性差内存占用较大 我们可以自定义RedisTempla…

NASA数据集——2015 年30 米分辨率的地衣地面覆盖率模型估计值

cABoVE: Lichen Forage Cover over Fortymile Caribou Range, Alaska and Yukon, 2000-2015 文件修订日期:2021-07-21 数据集版本: 1 摘要 本数据集提供了美国阿拉斯加东部内陆和加拿大育空地区 Fortymile 研究区 2015 标称年 30 米分辨率的地衣地面覆盖率模型估…

YOLOv8-ROS-noetic+USB-CAM目标检测

环境介绍 Ubuntu20.04 Ros1-noetic Anaconda-yolov8虚拟环境 本文假设ROS和anaconda虚拟环境都已经配备,如果不知道怎么配备可以参考: https://blog.csdn.net/weixin_45231460/article/details/132906916 创建工作空间 mkdir -p ~/catkin_ws/srccd ~/ca…

湖北专升本报名照片需要<40kb怎么解决

湖北专升本报名照片需要<40kb怎么解决

vue 修改element-plus主题色

一、安装SCSS npm install sass --save-dev npm install sass-loader --save-dev npm install node-sass --save-dev npm install vue-style-loader --sava-dev 二、添加主题文件theme.scss forward "element-plus/theme-chalk/src/common/var.scss" with ($col…

kubernetes负载均衡-service

一、service的概念 1、什么是service 在Kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;当我们需要访问这个应用时&#xff0c;可以通过Pod的IP进行访问&#xff0c;但是这里有两个问题:1、Pod的IP地址不固定&#xff0c;一旦Pod异常退出、节点故障&#xff0c;则会…

【STM32】读写BKP备份寄存器RTC实时时钟

目录 BKP BKP简介 BKP基本结构 BKP测试代码 RTC RTC简介 RTC框图 RTC基本结构 硬件电路 RTC操作注意事项 接线图 初始化 使用BKP解决只初始化一次时间 初始化参考代码 RTC设置时间 RTC读取时间 完整代码 MyRTC.c MyRTC.h main.c BKP BKP简介 BKP&#xff0…

pytorch中tensor类型转换的几个函数

目录 IntTensor转FloatTensor FloatTensor转IntTensor Tensor类型变为python的常规类型 IntTensor转FloatTensor .float函数&#xff1a; FloatTensor转IntTensor .int函数 Tensor类型变为python的常规类型 item函数