-
-
Save mob-sakai/b98a62c1f2c94c1fef9021101635a5cd to your computer and use it in GitHub Desktop.
using UnityEngine; | |
using UnityEditor; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Text; | |
using System.Linq; | |
using System; | |
/// <summary> | |
/// Remove empty folders automatically. | |
/// </summary> | |
public class RemoveEmptyFolders : UnityEditor.AssetModificationProcessor | |
{ | |
public const string kMenuText = "Assets/Remove Empty Folders"; | |
static readonly StringBuilder s_Log = new StringBuilder(); | |
static readonly List<DirectoryInfo> s_Results = new List<DirectoryInfo>(); | |
/// <summary> | |
/// Raises the initialize on load method event. | |
/// </summary> | |
[InitializeOnLoadMethod] | |
static void OnInitializeOnLoadMethod() | |
{ | |
EditorApplication.delayCall += () => Valid(); | |
} | |
/// <summary> | |
/// Raises the will save assets event. | |
/// </summary> | |
static string[] OnWillSaveAssets(string[] paths) | |
{ | |
// If menu is unchecked, do nothing. | |
if (!EditorPrefs.GetBool(kMenuText, false)) | |
return paths; | |
// Get empty directories in Assets directory | |
s_Results.Clear(); | |
var assetsDir = Application.dataPath + Path.DirectorySeparatorChar; | |
GetEmptyDirectories(new DirectoryInfo(assetsDir), s_Results); | |
// When empty directories has detected, remove the directory. | |
if (0 < s_Results.Count) | |
{ | |
s_Log.Length = 0; | |
s_Log.AppendFormat("Remove {0} empty directories as following:\n", s_Results.Count); | |
foreach (var d in s_Results) | |
{ | |
s_Log.AppendFormat("- {0}\n", d.FullName.Replace(assetsDir, "")); | |
FileUtil.DeleteFileOrDirectory(d.FullName); | |
} | |
// UNITY BUG: Debug.Log can not set about more than 15000 characters. | |
s_Log.Length = Mathf.Min(s_Log.Length, 15000); | |
Debug.Log(s_Log.ToString()); | |
s_Log.Length = 0; | |
AssetDatabase.Refresh(); | |
} | |
return paths; | |
} | |
/// <summary> | |
/// Toggles the menu. | |
/// </summary> | |
[MenuItem(kMenuText)] | |
static void OnClickMenu() | |
{ | |
// Check/Uncheck menu. | |
bool isChecked = !Menu.GetChecked(kMenuText); | |
Menu.SetChecked(kMenuText, isChecked); | |
// Save to EditorPrefs. | |
EditorPrefs.SetBool(kMenuText, isChecked); | |
OnWillSaveAssets(null); | |
} | |
[MenuItem(kMenuText, true)] | |
static bool Valid() | |
{ | |
// Check/Uncheck menu from EditorPrefs. | |
Menu.SetChecked(kMenuText, EditorPrefs.GetBool(kMenuText, false)); | |
return true; | |
} | |
/// <summary> | |
/// Get empty directories. | |
/// </summary> | |
static bool GetEmptyDirectories(DirectoryInfo dir, List<DirectoryInfo> results) | |
{ | |
bool isEmpty = true; | |
try | |
{ | |
isEmpty = dir.GetDirectories().Count(x => !GetEmptyDirectories(x, results)) == 0 // Are sub directories empty? | |
&& dir.GetFiles("*.*").All(x => x.Extension == ".meta"); // No file exist? | |
} | |
catch | |
{ | |
} | |
// Store empty directory to results. | |
if (isEmpty) | |
results.Add(dir); | |
return isEmpty; | |
} | |
} |
Great gist! Would you consider adding an MIT license header to it? :)
Great work!
Really Good !
doesnt work with 2020.1 - looks like the deletion of the meta files doesnt work
get following error for all directories that should be deleted
"A meta data file (.meta) exists but its folder '****' can't be found, and has been created. Empty directories cannot be stored in version control, so it's assumed that the meta data file is for an empty directory in version control. When moving or deleting folders outside of Unity, please ensure that the corresponding .meta file is moved or deleted along with it."
Found solution for 2020.2+:
delete the meta file instead of the directory
Solution 2020.2: Lines 48:
FileUtil.DeleteFileOrDirectory(d.FullName);
FileUtil.DeleteFileOrDirectory(d.Parent + "\\" + d.Name + ".meta"); // unity 2020.2 need to delete the meta too
Solution 2020.2: Lines 48:
FileUtil.DeleteFileOrDirectory(d.FullName); FileUtil.DeleteFileOrDirectory(d.Parent + "\\" + d.Name + ".meta"); // unity 2020.2 need to delete the meta too
This worked for me. I wrote it this way
foreach (var d in s_Results)
{
// Line 1: s_Log.AppendFormat("- {0}\n", d.FullName.Replace(assetsDir, ""));
FileUtil.DeleteFileOrDirectory(d.FullName);
FileUtil.DeleteFileOrDirectory(d.Parent + "\\" + d.Name + ".meta"); // unity 2020.2 need to delete the meta too
}
I wonder if // Line 1: s_Log.AppendFormat("- {0}\n", d.FullName.Replace(assetsDir, ""));
is required
It is achievable without using IO. This is a context version, select folders to clean up, right click > Delete Empty Folders.
You can adapt it for project wide if you dare.
namespace Framework.Editor.Extensions
{
using UnityEngine;
using UnityEditor;
internal static class DeleteEmptyFolders
{
[MenuItem("Assets/Delete Empty Folders")]
static void deleteEmptyFolders()
{
foreach (var item in Selection.objects)
{
TryDeleteEmptyFolders(item);
}
}
private static void TryDeleteEmptyFolders(UnityEngine.Object obj)
{
if (!AssetDatabase.IsMainAsset(obj))
return;
// checks if the asset is a folder
if (obj.GetType() != typeof(UnityEditor.DefaultAsset))
return;
string dir = AssetDatabase.GetAssetPath(obj);
var subdirs = AssetDatabase.GetSubFolders(dir);
string[] strBuffer = new string[1];
foreach (var sub in subdirs)
{
strBuffer[0] = sub;
var assets = AssetDatabase.FindAssets("*", strBuffer);
if(assets.Length == 0)
{
Debug.Log("Deleteing : " + sub);
AssetDatabase.MoveAssetToTrash(sub);
}
}
}
}
}
Need to change line 97
.All(x => x.Extension == ".meta" || x.Name.Contains("DS_Store")); // No important files?
In Mac there are hidden files called .DS_Store.
Overview
Remove empty directories by
OnWillSaveAssets
callback.To turn on/off, toggle menu
Assets > Remove Empty Folders
.Default is
OFF
.When empty directories have been removed, put a log.