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

news2024/10/6 12:32:19

前沿

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.executable
    else:
        # 程序未被打包,使用 __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_path

    return self_path


SimplifyPath = {}
#对路径进行简化,隐藏过多的上级目录
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_path
        return simplified_path
    else:
        # 如果路径级别不多于max_levels,不做改变直接返回,并将结果存储在字典中
        #SimplifyPath[path] = path
        return path

Total_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 = 0
            is_clean= False
            for 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 += 1
                            is_clean = True
            if is_clean : 
                print(YELLOW+"2. 清理了{0}个文件 - 目录:{1}".format(trash_number,simplify_path(dir_path))+RESET)
                print(YELLOW+"-----总共清理了{0}个工程-----".format(Total_DelectNumber)+RESET)
                Total_DelectNumber += 1
            else: print(YELLOW+"3. 已经是干净的目录了:{0}".format(simplify_path(dir_path))+RESET)

            return True
        return 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):
            return


        cleaned = False
        full_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 match
                if is_match_and_clean(full_path):
                    cleaned = True
                    continue  # break | Stop searching this level once a match is found and cleaned
                else:
                    # Recursively traverse the subdirectory
                    traverse_and_clean(full_path, current_depth + 1)
        if cleaned:
            # 如果对此目录进行清理了,则跳过这个级别的剩余目录
            return

    traverse_and_clean(root_path)

# find_and_clean_directories("/path/to/root", ["A", "B", "C"], ["D", "E.txt"])


main()

效果展示

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

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

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

相关文章

2024-03-22 问AI: 介绍一下深度学习中的 sigmoid函数

文心一言 Sigmoid函数是深度学习中常用的一种激活函数,主要用于将神经元的输出值压缩到0和1之间。这种特性使得sigmoid函数在二分类问题中特别有用,因为输出值可以被解释为属于某个类别的概率。 sigmoid函数的数学表达式为: σ(x) 1 / (1…

Notepad++ 如何调整显示字面大小

在 Notepad 上,可以使用 ctrl 加上鼠标的左键来滚动来进行调整。 如何恢复默 可以使用 Ctrl 加数字键盘上的 / 键 来恢复默认设置。 当然也可以通过菜单栏上 view 菜单下的 Zoom 选项。 上面的界面中可以看到我们的在 Notepad 中使用的选项。 Notepad 如何调整显示…

llvm后端

SelectionDAGBuilder是LLVM(Low Level Virtual Machine)编译器中的一个重要组件,它负责将LLVM中间表示(Intermediate Representation,IR)转换为SelectionDAG(选择有向无环图)的形式。…

RabbitMq高可用

消息队列高级 服务异步通信-高级篇1.消息可靠性1.1.生产者消息确认1.2.消息持久化1.3.消费者消息确认1.4.消费失败重试机制1.5.总结 2.死信交换机2.1.初识死信交换机2.2.TTL2.3.延迟队列 3.惰性队列3.1.消息堆积问题3.2.惰性队列 4.MQ集群4.1.集群分类4.2.普通集群4.3.镜像集群…

C#,图论与图算法,计算图(Graph)的岛(Island)数量的算法与源程序

1 孤岛数 给定一个布尔矩阵,求孤岛数。一组相连的1形成一个岛。例如,下面的矩阵包含5个岛: 在讨论问题之前,让我们先了解什么是连接组件。无向图的连通分量是一个子图,其中每两个顶点通过一条路径相互连接,并且不与子图外的其他顶点连接。 所有顶点相互连接的图只有一个…

Spring05 SpringIOC DI

名词解释 今天我们来介绍Spring框架的最重要的part之一 SpringIOC 和 DI 这里的SpringIOC 其实是容器的意思,Spring是一个包含了很多工具方法的IOC容器 什么是IOC呢? IOC其实是Spring的核心思想 Inversion of Control (控制反转) 可能这里你还是不理解这个是啥意思 其实就…

xilinx的高速接口构成原理和连接结构

本文来源: V3学院 尤老师的培训班笔记【高速收发器】xilinx高速收发器学习记录Xilinx-7Series-FPGA高速收发器使用学习—概述与参考时钟GT Transceiver的总体架构梳理 文章目录 一、概述:二、高速收发器结构:2.1 QUAD2.1.1 时钟2.1.2 CHANNEL…

【SysBench】OLTP 基准测试示例

前言 本文采用 MySQL 沙盒实例作为测试目标,使用 sysbench-1.20 对其做 OLTP 基准测试。 有关 MySQL 沙盒的更多信息,请参阅 玩转 MySQL Shell 沙盒实例,【MySQL Shell】6.8 AdminAPI MySQL 沙盒 。 1、部署一个 MySQL 沙盒实例 使用 mysq…

【ESP32S3 Sense接入百度在线语音识别】

视频地址: 1. 前言 使用Seeed XIAO ESP32S3 Sense开发板接入百度智能云实现在线语音识别。自带麦克风模块用做语音输入,通过串口发送字符“1”来控制数据的采集和上传。 步骤概括    (1) 在百度云控制端选择“语音识别”并创建应用获取API Key和Secr…

MapReduce学习问题记录

1、如何跳过对某行数据的处理 第一行数据是字段名不需要处理,我们知道第一行偏移量是0(行记录的时候是从数组首地址开始,到了行标识符进行一次计数,这个计数就是行偏移量,从0开始),我们根据偏移…

银行5G短消息应用架构设计

(一)RCS简介 1.1 RCS的提出与标准制定 RCS(Rich Communication Services & Suite,富媒体通信)是GSMA(Groupe Speciale Mobile Association,全球移动通信系统协会)在2008年提出的一种通讯方式,RCS融合了语音、消息…

【算法每日一练]-图论(保姆级教程篇16 树的重心 树的直径)#树的直径 #会议 #医院设置

目录 树的直径 题目:树的直径 (两种解法) 做法一: 做法二: 树的重心: 题目: 会议 思路: 题目:医院设置 思路: 树的直径 定义:树中距离最…

android.os.TransactionTooLargeException解决方案,Kotlin

android.os.TransactionTooLargeException解决方案,Kotlin 首先,特意制造一个让Android发生TransactionTooLargeException的场景,一个Activity启动另外一个Activity,在Intent的Bundle里面塞入一个大的ArrayList: import android.…

阿里云OSS存储的视频如何加水印

OSS是不能进行视频添加水印的,可以图片添加水印。 您可以在视频点播中进行配置: https://help.aliyun.com/zh/vod/user-guide/video-watermarks?spma2c4g.11186623.0.i2 原来的业务代码都是使用python 对oss的 视频进行上传 的,上传的视频路径已经保存到…

设计数据库之外部模式:数据库的应用

Chapter5:设计数据库之外部模式:数据库的应用 笔记来源:《漫画数据库》—科学出版社 设计数据库的步骤: 概念模式 概念模式(conceptual schema)是指将现实世界模型化的阶段进而,是确定数据库理论结构的阶段。 概念模…

系统架构设计-构建系统应用

1. 系统架构目标与设计原则 在设计系统架构时,我们的目标是确保系统具有以下特点: 可靠性:系统能够持续稳定运行,保证业务可用性。可伸缩性:系统能够根据负载变化自动扩展或收缩,以应对不同的流量需求。容…

【Java高级】利用反射机制获取类的所有信息

文章目录 1.相关准备2.导航图3. 相关的方法----------------------------------------------类------------------------------------------------------1 类的修饰符2 类名 -----------------------------------------------属性--------------------------------------------…

FileZilla 链接服务器提示 20 秒连接超时

FileZilla 有个默认设置是如果 20 秒没有数据的话会自动中断链接。 Command: Pass: **************** Error: Connection timed out after 20 seconds of inactivity Error: Could not connect to server修改配置 这个配置是可以修改的,修改的步骤为: …

保研复习概率论1

1.什么是随机试验(random trial)? 如果一个试验满足试验可以在相同的条件下重复进行、试验所有可能结果明确可知(或者是可知这个范围)、每一次试验前会出现哪个结果事先并不确定,那么试验称为随机试验。 …

零基础机器学习(4)之线性回归的基本原理

文章目录 一、线性回归的基本原理1.相关与回归2.线性回归的原理分析①线性回归的一般公式②线性回归的损失函数③线性回归方程的参数求解方法A.最小二乘法B.梯度下降法 一、线性回归的基本原理 1.相关与回归 相关描述的是变量之间的一种关系。 从统计角度看,变量之…