#!/bin/bash # images-cleaner.sh ##################### # # This script looks at each image filename in [IMAGE_DIR] and searches for the # filename in the equivalent [GAMELIST_DIR] gamelist.xml matching the system. # Change the default directories if needed # # WARNING: Images will be deleted unless -t|--test option is supplied # # Run the script with '--help' to get more info. # # sano - initial code in forum post # kaltinril - 2017-08-20 - converted into script with command-line arguments # # TODO: # 1. find every image file (png|jpg) on ~/.emulationstation/downloaded_images/ # 2. loop every file searching for an occurrence in the respective gamelist. # 2.1 if there's no occurrence, delete it. # Global Variables REPLACE_GAMELIST=false GAMELISTS_DIR="$HOME/.emulationstation/gamelists" IMAGES_DIR="$HOME/.emulationstation/downloaded_images" SYSTEM= SYSTEM_DIR= TEST_ONLY=false SUMMMARY_ONLY=false IMAGES_DELETED=0 SYSTEMS_CHECKED=0 IMAGES_FILESIZE=0 # Read only Variables readonly SCRIPT_DIR="$(dirname "$0")" readonly SCRIPT_NAME="$(basename "$0")" readonly SCRIPT_FULL="$SCRIPT_DIR/$SCRIPT_NAME" readonly SCRIPT_URL="https://raw.githubusercontent.com/meleu/share/master/images-cleaner.sh" readonly USAGE="Usage: $0 [OPTIONS] [gamelist.xml]... " readonly EXAMPLE="Examples: Normal: $0 Test only: $0 -t Summary only: $0 -s Gamelist dir: $0 -g /home/pi/RetroPie/roms Images dir: $0 -i /home/pi/.emulationstation/downloaded_images " readonly HELP=" This script looks at each image filename in IMAGE_DIR and searches for the filename in the equivalent GAMELIST_DIR gamelist.xml matching the system. Change the default directories if needed WARNING: Images will be deleted unless -t|--test option is supplied $USAGE $EXAMPLE The OPTIONS are: -h|--help print this message and exit. -u|--update update the script and exit. -t|--test test only, do not actually delete anything. -i|--images DIR specifies the IMAGEs directory. Default: $IMAGES_DIR -g|--gamelist DIR specifies the gamelist directory. Default: $GAMELISTS_DIR -y|--system SYSTEM explicitly says which system's gamelist.xml you want to clean. -s|--summary only print a summary when done. " function update_script() { local err_flag=0 local err_msg if err_msg=$(wget "$SCRIPT_URL" -O "/tmp/$SCRIPT_NAME" 2>&1); then if diff -q "$SCRIPT_FULL" "/tmp/$SCRIPT_NAME" >/dev/null; then echo "You already have the latest version. Nothing changed." rm -f "/tmp/$SCRIPT_NAME" exit 0 fi err_msg=$(mv "/tmp/$SCRIPT_NAME" "$SCRIPT_FULL" 2>&1) \ || err_flag=1 else err_flag=1 fi if [[ $err_flag -ne 0 ]]; then err_msg=$(echo "$err_msg" | tail -1) echo "Failed to update \"$SCRIPT_NAME\": $err_msg" >&2 exit 1 fi chmod a+x "$SCRIPT_FULL" echo "The script has been successfully updated. You can run it again." exit 0 } function print_summary() { echo echo "Summary of work:" [[ "$TEST_ONLY" == true ]] && echo " - TEST ONLY, NO DELETIONS" echo " - Systems checked: $SYSTEMS_CHECKED" echo " - Images deleted: $IMAGES_DELETED" echo " - Space freed: $IMAGES_FILESIZE" } function images_loop() { sys="$1" if [[ -n "$SYSTEM_DIR" ]]; then images_directory="$IMAGES_DIR" gamelist_directory="$GAMELISTS_DIR" else images_directory="$IMAGES_DIR/$sys" gamelist_directory="$GAMELISTS_DIR/$sys" fi # Loop over all the images in the system for file in "$images_directory"/* do # XML Encode the & symbol cfile=`echo $file | sed s/\&/\&\;/g` # Get just the filename and extension, we don't care about the path really, and, it might not be there. cfile=$(basename "$cfile") file_size=$(stat -c%s "$file") # If no gamelist is found, could be user supplied bad root gamelist folder if [[ ! -s "$gamelist_directory/gamelist.xml" ]]; then echo "ERROR: Could not find gamelist for system '$sys' at location \"$gamelist_directory\"" >&2 echo "Try to explicitly give its directory with '--gamelist' option." >&2 break fi # Check for the image in the gamelist, grep return code 0 if found, 1 if not, 2 if error grep_result=$(grep -q -F "$cfile" $gamelist_directory/gamelist.xml) grep_rc=$? # Another check, being certain the gamelist was found if [ "$grep_rc" == "2" ] ; then echo "ERROR: Unable to access gamelist for system $sys at location \"$gamelist_directory\"" >&2 echo "ERROR: File was: $cfile" >&2 break fi # If the image filename was NOT found in the system's gamelist, delete it if [[ "$grep_rc" == "1" ]]; then ((++IMAGES_DELETED)) IMAGES_FILESIZE=$((IMAGES_FILESIZE + file_size)) [[ "$SUMMMARY_ONLY" == false ]] && echo "Deleting: $file" [[ "$TEST_ONLY" == false ]] && rm "$file" fi done } # Get all the user passed in arguments while [[ $# -gt 0 ]]; do case "$1" in -h|--help) echo "$HELP" >&2 exit 0 ;; -u|--update) update_script ;; -g|--gamelist) shift GAMELISTS_DIR="$1" ;; -i|--images) shift IMAGES_DIR="$1" ;; -y|--system) shift SYSTEM="$1" SYSTEM_DIR="$HOME/RetroPie/roms/$SYSTEM" if [[ ! -d "$SYSTEM_DIR" ]]; then echo "ERROR: Looks like \"$SYSTEM\" is not a valid console (directory '$SYSTEM_DIR' not found)." echo "Please enter a valid system." exit 1 fi ;; -t|--test) TEST_ONLY=true echo " ==TESTING MODE==" ;; -s|--summary) SUMMMARY_ONLY=true ;; *) echo "ERROR: \"$1\": invalid option" >&2 echo "$HELP" >&2 exit 1 ;; esac shift done if [[ -n $SYSTEM ]]; then images_loop "$SYSTEM" else # Loop over all systems in the images folder for sys in $IMAGES_DIR/* do [[ -d "$sys" ]] || continue # Extract just the basename sys=$(basename "$sys") echo [[ "$SUMMMARY_ONLY" == false ]] && echo "Working on system: $sys" ((++SYSTEMS_CHECKED)) images_loop "$sys" done fi print_summary