Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Python script for removing unused PNG files from the Defold project
import os, sys, hashlib, stat
import deftree, configparser
PROJECT_FILE = "game.project"
def all_files(ending):
# Generator to get files
for root, folders, files in os.walk(project_root):
for f in files:
if f.endswith(ending):
yield os.path.join(root, f)
def get_attribute(root, attribute_name):
# To simplify getting all images in an atlas
for x in root.iter():
if deftree.is_element(x):
get_attribute(x, attribute_name)
if == attribute_name:
yield x
def image_in_file(atlas):
# Returns all images in an atlas
tree = deftree.parse(atlas)
root = tree.get_root()
images = []
for x in get_attribute(root, "image"):
return images
def image_in_cubemap(cubemap):
# Returns all images in a cubemap
tree = deftree.parse(cubemap)
root = tree.get_root()
images = []
for child in root.iter():
if str(child).endswith(".png\""):
return images
def unused_png_remover(project_root):
output = []
files_with_images = {}
config = configparser.ConfigParser(), PROJECT_FILE))
config_images = []
for key in config:
for value in config[key]:
if config[key][value].endswith(".png"):
files_with_images[PROJECT_FILE] = config_images
for x in all_files(".tilesource"):
name = os.path.basename(x)
files_with_images[name] = image_in_file(x)
for x in all_files(".atlas"):
name = os.path.basename(x)
files_with_images[name] = image_in_file(x)
for x in all_files(".cubemap"):
name = os.path.basename(x)
files_with_images[name] = image_in_cubemap(x)
# Iterate over all images and remove unused
for x in all_files(".png"):
count = 0
img = "/" + x.replace(project_root, "").replace("\\", "/")
for file in files_with_images:
if img in files_with_images[file]:
count += 1
if count == 0:
path = project_root + img
output.append({"file": img, "size": os.stat(path)[stat.ST_SIZE]})
return output
def empty_folder_cleaner(project_root):
counter = 0
remove_dir = True
while remove_dir:
remove_dir = False
for dir, subdirs, files in os.walk(project_root, topdown=False):
if not subdirs and not files: #check whether the directory is now empty after deletions, and if so, remove it
print("Folder {} removed".format(dir))
counter = counter + 1
remove_dir = True
return counter
def sizeof_fmt(num, suffix):
for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
if len(sys.argv) > 1:
project_root = sys.argv[1]
if os.path.exists(project_root):
# Adds all atlases and its images to a dictionary
output = unused_png_remover(project_root)
#empty folders remove
count_of_folders = empty_folder_cleaner(project_root)
#Print log
total_size = 0
for x in output:
print("File {} removed. {}".format(x["file"], sizeof_fmt(x["size"], "B")))
total_size = total_size + x["size"]
print("{} files and {} folders was removed. {} ".format(len(output), count_of_folders, sizeof_fmt(total_size, "B")))
print('Usage: python project_folder')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment