I wrote a script to list (and optionally delete) the image files it finds in a directory that are not referenced any where. I specified a single sub-directory at a time. If you do the entire project it may take long to complete.
#!/bin/bash PROJECT_DIR="$PWD" IMAGE_DIR="$PWD" DELETE_FLAG=false # Check for -d (delete) flag if [[ $1 == "-d" ]]; then DELETE_FLAG=true fi # Find all image files find $IMAGE_DIR -type f \( -iname \*.png -o -iname \*.jpg -o -iname \*.jpeg -o -iname \*.gif -o -iname \*.webp -o -iname \*.svg -o -iname \*.ico \) | while read img_file; do # Extract the basename of the image file img_basename=$(basename "$img_file") # Search for it in the project, excluding .zip files and .git directories result=$(grep -ril --exclude=*.zip --exclude-dir=.git "$img_basename" "$PROJECT_DIR") # If not found, print it or delete it based on flag if [ -z "$result" ]; then echo "Unused image: $img_file" if $DELETE_FLAG; then rm "$img_file" echo "Deleted: $img_file" fi fi done
Be sure to edit the code to include the image file types that you want to target. Make the file executable before trying to use it:
chmod +x find_unused_images.sh
Run the script (without deletion)
./find_unused_images.sh
To run the script with the delete functionality:
./find_unused_images.sh -d
In an early version, my script was leaving behind files that appeared to be completely unreferenced in the code base (I checked manually by searching the project via IDE). To troubleshoot, I ran grep
from the command line:
grep -ril "experienceLogo2.png" "$PWD"
It turned out that those files were referenced in a zip file and in git objects (and therefore considered not unused). I fixed this bug by adding the flags –exclude=*.zip –exclude-dir=.git to my grep
command in find_unused_images.sh.
I had lots of unused stock images and old designs that felt good to purge. Now with generative image AI, I know I could create assets easily as I need them in the future.
I used this script during a project to upgrade my website to use next generation file formats. If you liked this post, read another one where I discuss managing graphic assets for a web project.
Update
Identify any unused files in a code project
This code can be changed to search for any kind of file. Here’s an updated version I used to see if some old Bootstrap files were being used any where:
#!/bin/bash PROJECT_DIR="$PWD" FILE_DIR="$PWD/css" DELETE_FLAG=false # Check for -d (delete) flag if [[ $1 == "-d" ]]; then DELETE_FLAG=true fi # Find all image files # find $FILE_DIR -type f \( -iname \*.png -o -iname \*.jpg -o -iname \*.jpeg -o -iname \*.gif -o -iname \*.webp -o -iname \*.svg -o -iname \*.ico \) | while read my_file; do find $FILE_DIR -type f \( -iname \*.css -o -iname \*.js \) | while read my_file; do # Extract the basename of the image file file_basename=$(basename "$my_file") # Search for it in the project, excluding .zip files and .git directories and .xml directories result=$(grep -ril --exclude=*.zip --exclude-dir=.git --exclude=*.xml "$file_basename" "$PROJECT_DIR") # If not found, print it or delete it based on flag if [ -z "$result" ]; then echo "Unused file: $my_file" if $DELETE_FLAG; then rm "$my_file" echo "Deleted: $my_file" fi fi done
This didn’t work perfectly. I had to add an exclusion condition for .xml files because my WordPress blog archive files were being highlighted in the search. (EOD, I ended up zipping the few .xml archive files anyway. I also keep them on an S3 bucket, but I enjoy redundancy.)
The file name “bootstrap.css” was being found in its own file.
This, at least, gave me enough confidence to just delete the files manually. I can’t call this a perfect tool (and I don’t think it would scale well), but it is a utility for a practical use-case.
I saw other examples of it acting funny. For instance, I had an old stock photo file named ‘5.jpg’. It was coming up as being used in the project because, for some reason, that string was found in another image file – ‘jimmy.webp’.