Clearing out Synology @eaDir folders in your music collection

Greetings Synology Users!

When I moved to the Docker version of Roon on Synology recently, I decided to sunset Synology Audio Station for now. If you, like me, have been running Roon on Synology, you’ve undoubtedly noticed that the number of files it scans is wildly larger than the number of music files and folders you have. For instance, for my collection of ~65,000 tracks, there were over 370,000 files to scan. Most of those files are hidden metadata files that Synology creates (“sidecars” in @eaDir folders) when you copy music to your NAS. That information is most useful to Synology Audio Station, but if you aren’t running Audio Station, they are a waste. I created a shell script with ChatGPT that you can use to clear these things out. Please use at your own risk - but note in the instructions at the top there is a way to run a test before you use it. Make sure it is executable before you run it. It will put a log into a file named like /tmp/eadir-cleanup-YYYYMMDD-HHMMSS.log.

Make sure that Audio Station is stopped and/or uninstalled before running this.

Once you perform the cleanout, Roon will have FAR fewer files to scan and…depending upon the size of your collection it will even begin to pick up music automatically, without a Force Rescan!

(Note: the --reindex option is there just in case you DO want to use Audio Station and want a new, more efficient, up-to-date set of metadata for Audio Station.)

Enjoy!

#!/bin/sh

# Remove Synology @eaDir folders from a music collection.
# Default mode is DRY RUN. Nothing is deleted unless --delete is supplied.
#
# Usage:
#   sh clean-synology-eadir.sh /volume1/music
#   sudo sh clean-synology-eadir.sh /volume1/music --delete
#   sudo sh clean-synology-eadir.sh /volume1/music --delete --reindex

set -u

MUSIC_ROOT="${1:-}"
DELETE_MODE="no"
REINDEX_MODE="no"

for arg in "$@"; do
  case "$arg" in
    --delete)
      DELETE_MODE="yes"
      ;;
    --reindex)
      REINDEX_MODE="yes"
      ;;
  esac
done

if [ -z "$MUSIC_ROOT" ]; then
  echo "ERROR: Please specify your music root folder."
  echo "Example: sh clean-synology-eadir.sh /volume1/music"
  exit 1
fi

if [ "$MUSIC_ROOT" = "/" ]; then
  echo "ERROR: Refusing to run against /"
  exit 1
fi

if [ ! -d "$MUSIC_ROOT" ]; then
  echo "ERROR: Folder does not exist: $MUSIC_ROOT"
  exit 1
fi

LOG_FILE="/tmp/eadir-cleanup-$(date +%Y%m%d-%H%M%S).log"

echo "Music root: $MUSIC_ROOT"
echo "Log file:   $LOG_FILE"

if [ "$DELETE_MODE" = "yes" ]; then
  echo "Mode:       DELETE"
else
  echo "Mode:       DRY RUN"
fi

echo ""
echo "Scanning for @eaDir folders..."
echo ""

# Count first, safely pruning each @eaDir once found.
COUNT=$(find "$MUSIC_ROOT" -type d -name '@eaDir' -prune -print | tee "$LOG_FILE" | wc -l | tr -d ' ')

echo ""
echo "Found $COUNT @eaDir directories."
echo "List saved to: $LOG_FILE"
echo ""

if [ "$COUNT" = "0" ]; then
  echo "Nothing to remove."
  exit 0
fi

if [ "$DELETE_MODE" != "yes" ]; then
  echo "DRY RUN ONLY. Review the log file first."
  echo ""
  echo "To actually delete them, run:"
  echo "  sudo sh clean-synology-eadir.sh \"$MUSIC_ROOT\" --delete"
  exit 0
fi

echo "Deleting @eaDir directories..."
echo ""

# Delete using the logged list. This handles spaces, apostrophes, parentheses, etc.
# It does not handle newlines in path names, which should not be an issue for normal music folders.
while IFS= read -r dir; do
  if [ -d "$dir" ] && [ "$(basename "$dir")" = "@eaDir" ]; then
    echo "Removing: $dir"
    rm -rf "$dir"
  fi
done < "$LOG_FILE"

echo ""
echo "Deletion complete."

if [ "$REINDEX_MODE" = "yes" ]; then
  echo ""
  echo "Requested reindex."

  if command -v synoindex >/dev/null 2>&1; then
    echo "Running: synoindex -R \"$MUSIC_ROOT\""
    synoindex -R "$MUSIC_ROOT"
    echo "Reindex command submitted."
  else
    echo "synoindex was not found on this NAS."
    echo "Use DSM: Control Panel > Indexing Service > Media Indexing."
  fi
fi

echo ""
echo "Done."
4 Likes