Odin Inspector 系列教程 --- Odin工具箱【一鍵查找重復文件】

前言:隨著項目進度的不斷開展,在工程文件里面或多或少總有那么幾個重復文件,或者名稱相同,或者MD5值相同(一樣的文件復制多份但是名稱不同)
筆者制作了這個基于Odin的一鍵查找工具,方便大家查找項目中被遺忘的文(la)(ji)

示例工程中已經寫好備注,方便各位同學魔改
歡迎感興趣的小伙伴,推送各種基于Odin制作的輕量工具

完整示例代碼
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Timeline;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using System.Threading;

public class OneKeySearchDuplicateFiles : SerializedScriptableObject
{
    private bool IsToggled;
    private int maxCount;
    private IEnumerator<FileInfo> fileInfoIEnumerator;

    [PropertySpace(10)]
    [Title("需要搜索的文件夾", "默認為Asset全目錄", titleAlignment: TitleAlignments.Split)]
    [FolderPath(ParentFolder = "Assets", RequireExistingPath = true, AbsolutePath = true)]
    [LabelText("選擇你要搜索的文件夾")]
    public string targetSearchFolder;


    [ShowInInspector]
    [DictionaryDrawerSettings(KeyLabel = "MD5值", ValueLabel = "文件名稱列表")]
    private Dictionary<string, List<string>> sameMD5Group = new Dictionary<string, List<string>>();

    [ShowInInspector]
    [DictionaryDrawerSettings(KeyLabel = "文件名稱", ValueLabel = "絕對路徑列表")]
    private Dictionary<string, List<string>> sameNameGroup = new Dictionary<string, List<string>>();

    [ShowInInspector]
    [TitleGroup("重復文件列表")]
    [HorizontalGroup("重復文件列表/重復文件")]
    [BoxGroup("重復文件列表/重復文件/MD5值相同", CenterLabel = true)]
    [PropertyOrder(1000)]
    [InfoBox("發現相同MD5值文件.", InfoMessageType.Error, "CheckSameMD5ResultGroup")]
    [ShowIf("$CheckSameMD5ResultGroup")]
    [DictionaryDrawerSettings(KeyLabel = "MD5值", ValueLabel = "相同MD5值文件名稱")]
    private Dictionary<string, List<string>> sameMD5Result5Group = new Dictionary<string, List<string>>();


    [BoxGroup("重復文件列表/重復文件/名稱值相同", CenterLabel = true)]
    [ShowInInspector]
    [PropertyOrder(1000)]
    [InfoBox("發現相同名稱文件.", InfoMessageType.Error, "CheckSameNameResultGroup")]
    [ShowIf("$CheckSameNameResultGroup")]
    [DictionaryDrawerSettings(KeyLabel = "相同文件名稱", ValueLabel = "對應絕對路徑列表")]
    private Dictionary<string, List<string>> sameNameResultGroup = new Dictionary<string, List<string>>();

    public bool CheckSameMD5ResultGroup()
    {
        return sameMD5Result5Group.Count > 0;
    }

    private bool CheckSameNameResultGroup()
    {
        return sameNameResultGroup.Count > 0;
    }

    [PropertySpace(10,20)]
    [ShowIf("@ IsToggled== false")]
    [Button("開始搜索", ButtonSizes.Large)]
    public void StartSearch()
    {
        if (string.IsNullOrEmpty(targetSearchFolder))
        {
            targetSearchFolder = Application.dataPath;
        }
        ResetData();
        DirectoryInfo directoryInfo = new DirectoryInfo(targetSearchFolder);
        var filesGroup = directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories).Where(x => x.Extension != ".meta");

        maxCount = filesGroup.Count();
        fileInfoIEnumerator = filesGroup.GetEnumerator();
        IsToggled = true;
        EditorApplication.update += Updte;
    }
    private void ResetData()
    {
        maxCount = 0;
        MaxCount = 0;
        sameMD5Group.Clear();
        sameNameGroup.Clear();
        sameMD5Result5Group.Clear();
        sameNameResultGroup.Clear();
        fileInfoIEnumerator = null;
    }
    /// <summary>
    /// 過濾掉沒有重復文件的數據
    /// </summary>
    private void FilterDictionary()
    {
        sameMD5Result5Group = sameMD5Group.Where(x => x.Value.Count > 1).ToDictionary(p=>p.Key, p => p.Value);
        sameNameResultGroup = sameNameGroup.Where(x => x.Value.Count > 1).ToDictionary(p => p.Key, p => p.Value);
    }

    [ReadOnly]
    [ProgressBar(0, "maxCount", DrawValueLabel = true, ValueLabelAlignment = TextAlignment.Left, ColorMember = "GetHealthBarColor", Height = 30)]
    [ShowInInspector]
    [HideLabel]
    [ShowIf("@ IsToggled== true")]
    public int MaxCount { get; set; }//繪制進度條

    private Color GetHealthBarColor(int value)
    {
        maxCount = maxCount == 0 ? 1 : maxCount;
        return Color.Lerp(Color.red, Color.green, Mathf.Pow((float)value / maxCount, 2));
    }
    public void Updte()
    {
        if (IsToggled)
        {
            if (fileInfoIEnumerator.MoveNext())
            {
                //獲取對應Hash值
                string hashValue = GetMD5HashFromFile(fileInfoIEnumerator.Current.FullName);
                if (!sameMD5Group.ContainsKey(hashValue))
                {
                    sameMD5Group[hashValue] = new List<string>();
                }
                sameMD5Group[hashValue].Add("名稱為:" + fileInfoIEnumerator.Current.Name);

                //獲取名稱
                string fileName = fileInfoIEnumerator.Current.Name;

                if (!sameNameGroup.ContainsKey(fileName))
                {
                    sameNameGroup[fileName] = new List<string>();
                }
                sameNameGroup[fileName].Add("路徑為:" + fileInfoIEnumerator.Current.FullName);

                ++MaxCount;
            }
            else
            {
                EditorApplication.update -= Updte;
                IsToggled = false;
                FilterDictionary();
                Debug.Log("<color=green>注銷</color>");
            }
        }
    }

    /// <summary>
    /// 計算文件MD5值
    /// </summary>
    /// <param name="fileFullName"></param>
    /// <returns></returns>
    public string GetMD5HashFromFile(string fileFullName)
    {
        try
        {
            FileStream file = new FileStream(fileFullName, FileMode.Open);
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(file);
            file.Close();
            return BitConverter.ToString(retVal).ToLower().Replace("-", "");
        }
        catch
        {
            throw;
        }
    }
}

更多教程內容詳見:革命性Unity 編輯器擴展工具 --- Odin Inspector 系列教程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容