前言:隨著項目進度的不斷開展,在工程文件里面或多或少總有那么幾個重復文件,或者名稱相同,或者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;
}
}
}