Skip to content

Instantly share code, notes, and snippets.

@codiini
Last active March 17, 2025 15:12
Show Gist options
  • Save codiini/6366d458df6fd888e525bc51735f7cae to your computer and use it in GitHub Desktop.
Save codiini/6366d458df6fd888e525bc51735f7cae to your computer and use it in GitHub Desktop.
A python script to find unused assets in your codebase, list them and delete them if the prompt is accepted
import os
import re
def find_unused_images(asset_dir, code_dir):
# Collect all image files (common extensions: jpg, png, gif, svg, webp)
image_extensions = ('.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp')
images = [os.path.join(dp, f) for dp, dn, filenames in os.walk(asset_dir) for f in filenames if f.lower().endswith(image_extensions)]
unused_images = []
for image in images:
image_name = os.path.basename(image) # Get the image file name
found = False
# Search for the image file name in the code directory
for dp, dn, filenames in os.walk(code_dir):
for file in filenames:
# Check relevant file types
if file.endswith(('.html', '.md', '.css', '.liquid', '.php')):
with open(os.path.join(dp, file), 'r', encoding='utf-8') as f:
if re.search(re.escape(image_name), f.read()):
found = True
break
if found:
break
# If the image is not found in any file, consider it unused
if not found:
unused_images.append(image)
return unused_images
# Paths to your assets and code directories
image_dir = './source'
code_dir = './build'
# Find unused images
unused_images = find_unused_images(image_dir, code_dir)
# Print the list of unused images
print("Unused images:")
for img in unused_images:
print(img)
# Confirm deletion
if unused_images:
delete = input("\nDo you want to delete these unused images? (yes/no): ").strip().lower()
if delete == 'yes':
for img in unused_images:
try:
os.remove(img)
print(f"Deleted: {img}")
except Exception as e:
print(f"Failed to delete {img}: {e}")
else:
print("No files were deleted.")
else:
print("No unused images found.")
@codiini
Copy link
Author

codiini commented Mar 17, 2025

Javascript version

import fs from "fs";
import path from "path";
import readline from "readline";

const imageExtensions = [".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp"];

// Define excluded files or directories (relative to the root folder)
const excludedPaths = new Set([
  "node_modules",
  ".git",
  "README.md",
  "config.json",
]);

function shouldExclude(filePath) {
  return [...excludedPaths].some((excluded) => filePath.includes(excluded));
}

function collectImages(dir) {
  let images = [];
  fs.readdirSync(dir).forEach((file) => {
    const fullPath = path.join(dir, file);
    if (shouldExclude(fullPath)) return;

    if (fs.statSync(fullPath).isDirectory()) {
      images = images.concat(collectImages(fullPath));
    } else if (imageExtensions.includes(path.extname(file).toLowerCase())) {
      images.push(fullPath);
    }
  });
  return images;
}

function searchInFiles(dir, imageName) {
  let found = false;

  function traverse(dir) {
    if (found) return;

    fs.readdirSync(dir).forEach((file) => {
      const fullPath = path.join(dir, file);
      if (shouldExclude(fullPath)) return;

      if (fs.statSync(fullPath).isDirectory()) {
        traverse(fullPath);
      } else if (/\.(html|md|css|liquid|php)$/i.test(file)) {
        const content = fs.readFileSync(fullPath, "utf-8");
        if (content.includes(imageName)) {
          found = true;
        }
      }
    });
  }

  traverse(dir);
  return found;
}

function findUnusedImages(assetDir, codeDir) {
  const images = collectImages(assetDir);
  const unusedImages = images.filter((image) => {
    const imageName = path.basename(image);
    return !searchInFiles(codeDir, imageName);
  });

  return unusedImages;
}

// Paths to your assets and code directories
const imageDir = "./source";
const codeDir = "./build";

// Find unused images
const unusedImages = findUnusedImages(imageDir, codeDir);

// Print unused images
console.log("Unused images:");
unusedImages.forEach((img) => console.log(img));

// Confirm deletion
if (unusedImages.length > 0) {
  const readLine = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  readLine.question("\nDo you want to delete these unused images? (yes/no): ", (answer) => {
    if (answer.trim().toLowerCase() === "yes") {
      unusedImages.forEach((img) => {
        try {
          fs.unlinkSync(img);
          console.log(`Deleted: ${img}`);
        } catch (error) {
          console.error(`Failed to delete ${img}: ${error.message}`);
        }
      });
    } else {
      console.log("No files were deleted.");
    }
    readLine.close();
  });
} else {
  console.log("No unused images found.");
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment