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.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()

效果展示

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于DA优化CNN-LSTM的负荷预测

今天给大家分享DA优化CNN-LSTM的负荷预测,主要从算法原理和代码实战展开。需要了解更多算法代码的,可以点击文章左下角的阅读全文,进行获取哦~需要了解智能算法、机器学习、深度学习和信号处理相关理论的可以后台私信哦,下一期分享…

基于springboot+vue的电影院购票系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

docker将本地镜像pull到阿里云和registry

目录 一、上次到阿里云服务器 1、制作一个带有vim功能的Ubuntu镜像 2、在阿里云上面创建镜像仓库 3、从阿里云仓库中上传和拉取镜像 二、上传镜像到本地私有库registry 1、下载镜像docker registry 2、运行私有库registry,相当于本地有个私有docker hub。 3…

Unity:2D

目录 1. 简介 2. 2D Sorting 3. 9-slicing Sprites 3.1 9-slicing and Colliders 4. Sprite Renderer 5. Sprite Creator 6. Sprite Editor 6.1 Slice 6.1 Resize polygons 6.2 Custom Outline 6.3 Custom Physics Shape 6.4 Secondary Textures 6.5 Data Provider…

Nginx 全局块配置 user 指令详解

1. 前言 user 指令用于配置运行 nginx 服务器的 worker 进程的用户和用户组,这样对于系统权限的访问控制更加精细和安全 如果你修改过 nginx.conf,那么就会看到文件第一行的 user 指令配置,默认是被注释掉的(默认使用 nobody 用户…

《边缘计算:连接未来的智慧之桥》

随着物联网、5G等技术的快速发展,边缘计算作为一种新兴的计算模式,正逐渐引起人们的广泛关注。边缘计算通过将数据处理和存储功能放置在距离数据产生源头更近的位置,实现了更快速、更可靠的数据处理和交换,为各行各业带来了前所未…

镁光的sdram手册阅读--MT48LCC16M16A2

镁光的sdram手册阅读–MT48LCC16M16A2 一、这个sdram的总容量是256Mb,MT48LC16M16A2对应的参数是:4Meg 16 4banks,也可表示为16M16。4164256Mbit。 1)其中,4Meg表示单个bank包含的存储单元个数,计算公式…

架构整洁之道-读书总结

1 概述 1.1 关于本书 《架构整洁之道》(Clean Architecture: A Craftsman’s Guide to Software Structure and Design)是由著名的软件工程师Robert C. Martin(又称为Uncle Bob)所著。这本书提供了软件开发和架构设计的指导原则…

查看文件信息:ls,pwd,操作文件:cd,touch,mkdir,rmdir,rm,cp,mv

目录 ls 选项 -l -a 隐藏文件存在的意义 -F -d -R pwd cd 选项 ​编辑 touch 选项 mkdir 选项 -p rmdir 选项 -p rm 选项 cp 选项 -r -R (和-r的区别) mv 移动目录 改名 选项 rm改为mv ls 显示当前目录下的文件 选项 (可以合并使用,有的也可以写…

linux centos 安装jenkins,并构建spring boot项目

首先安装jenkins,使用war包安装,比较简单,注意看下载的版本需要的JDK版本,官网下载https://www.jenkins.io/download/ 把下载好的war包放到服务器上,然后运行,注意8080端口的放行 # 前台运行并指定端口 ja…

目标检测的指标评估

目标检测模型的评价指标主要用于衡量模型的性能,特别是它在定位和识别目标方面的准确性。以下是一些常见的评价指标: 1. 精确度 (Precision): 表示检测到的目标中,正确检测到的目标所占的比例。精确度高意味着模型产生的误报(错误…

rabbitmq 3.9.29 docker mac 管理员页面无法打开

SyntaxError: Unexpected token ‘catch’ SyntaxError: Unexpected token ‘catch’ at EJS.Compiler.compile (http://127.0.0.1:15672/js/ejs-1.0.min.js:1:6659) at new EJS (http://127.0.0.1:15672/js/ejs-1.0.min.js:1:1625) at format (http://127.0.0.1:15672/js/main…

图床项目实战:从零搭建一个简易图床

项目背景与需求分析 随着互联网的发展,图片分享、存储和管理的需求日益增长。图床作为一种专门用于存储和分享图片的服务,受到了广大用户的欢迎。本项目旨在搭建一个简易的图床系统,满足用户上传、查看和删除图片的基本需求。 技术选型 本项…

微光图像增强算法学习记录(一)

微光图像增强(LLIE)旨在恢复照明并提高微光图像的可见性,本文对阅读的文献进行记录和分享,帮助回顾和大家建立学习资料。 文献一摘要及前沿摘选主要贡献网络结构实验结论 文献二摘要 文献三摘要主要贡献网络架构实验 文献四摘要实…

AGV|机器人导航识别二维码视觉传感器TDCS-0100与上位机PLC联机实例说明

目前二维码视觉导航的AGV出货量非常大,几乎都是仓储型AGV使用的导航方式。在地面或者天花板等位置标贴二维码作为标记点,通过扫描读取二维码信息和二维码相对相机的角度来确定当前位置。 本文重点介绍AGV|机器人导航识别二维码视觉传感器TDCS-0100与上位…

linux下线程分离属性

linux下线程分离属性 一、线程的属性---分离属性二、线程属性设置2.1 线程创建前设置分离属性2.2 线程创建后设置分离属性 一、线程的属性—分离属性 什么是分离属性? 首先分离属性是线程的一个属性,有了分离属性的线程,不需要别的线程去接合…

测试ALPHA开发板CAN1的设备树文件

一. 简介 前面一篇文章学习了 ALPHA开发板上的 CAN接口的设备节点信息,文章如下: ALPHA开发板修改CAN的设备树节点信息-CSDN博客 本文对设备树文件进行测试,即开发板加载 .dtb设备树文件。 二. 加载测试 CAN的设备树文件 1. 拷贝设备树…

认识String类

认识String类 前面我们学习了类和对象,这一小节咱们来谈String类 目录 认识String类前言一、String类的创建方式二、String引用类型的特点及方法1.存储内容2.String对象的比较3.字符串查找在这里插入图片描述4.转换(一)数字转为为字符串&…

Swift 结构化并发之全局 Actor 趣谈

概览 在 Swift 结构化并发构成的体系中,一个称为“演员”(Actor)的成员扮演了非常重要的角色,它被用来隔离和同步执行中的数据。 除了普通 Actor 以外,还有一个全局“演员”(Global Actor)的概念,它是做什么的?又有什么与众不同的长处呢? 在本篇博文中,您将学到如…

【Swagger】接口文档生成

文章目录 一、前后端分离开发流程二、YApi导入接口文档三、Swagger3.1 介绍3.2 使用步骤3.2.1 导入 knife4j 的maven依赖3.2.2 在配置类中加入 knife4j 相关配置3.2.3 配置类中设置静态资源映射3.2.4 访问测试 3.3 常用注解3.4 全局参数设置 四、YApi 与 Swagger 一、前后端分离…