#!/bin/bash # Set sleep to n seconds if you want to slow down execution # useful for debugging on fast systems SLEEP=0 # Extensions list EXTS=( acm jpg txt mod dds lwo geo anm par pcx ter wav ac X 3ds tga scn ) # Missing files log MISS_LOG=/tmp/mod_cleaner.mis MISS_COUNT=0 # Do not modify # Missing files log UNIQ_MISS_LOG=/tmp/mod_cleaner.mis.uniq UNIQ_MISS_COUNT=0 # Do not modify # Scenario list file SCN_LIST=/tmp/mod_cleaner.scn # Parsed files list PARSED_LOG=/tmp/mod_cleaner.parsed PARSED_COUNT=0 # Do not modify CHECKED_COUNT=0 # Do not modify # Files containing bad reference list BAD_FILE_LOG=/tmp/mod_cleaner.bad BAD_FILE_COUNT=0 # Do not modify # corresponding .geo files list GEO_FILE_LOG=/tmp/mod_cleaner.geo GEO_FILE_COUNT=0 # corresponding .dds files list DDS_FILE_LOG=/tmp/mod_cleaner.dds DDS_FILE_COUNT=0 touch $MISS_LOG $PARSED_LOG $SCN_LIST $UNIQ_MISS_LOG $BAD_FILE_LOG $GEO_FILES ####################################################################################################################### # Load file function ;-) function load_file { ((CHECKED_COUNT++)) # File to parse local FILE=$1 # Full path dir name containing $FILE local DIR=`dirname $FILE` # File name referencing $FILE local FROM=$2 # $FILE name (without full path for easy display purpose) local BASE_FILE=`basename $FILE` # $FROM name (without full path for easy display purpose) local BASE_FROM=`basename $FROM` # Report missing file if $FILE does not exist if [ -f $FILE ] then # Abort if file is already parsed if [ `grep $FILE $PARSED_LOG | wc -l` -eq 0 ] then echo $FILE >> $PARSED_LOG # Increment parsed file number ((PARSED_COUNT++)) else printf '\033[13;1H\033[J'"Type\t\t: Already parsed (Yes !)\n" return fi # Abort if file is not text file (we do not need to parse binary files like .jpg) if [ `file $FILE | grep -i text | wc -l` -ne 1 ] then printf '\033[13;1H\033[J'"Type\t\t: Not a text file !\n" return fi local MATCH_LIST=/tmp/mod_cleaner_$BASE_FILE.match for EXT in ${EXTS[*]} do rm -f $MATCH_LIST rm -f $MATCH_LIST.2 # extract all file name with $EXT extension contained in $FILE if [ "$EXT" == "ac" ] then # We only want .ac files, not .acm file cat $FILE | grep -i "\.$EXT" | grep -vi "\.acm" >> $MATCH_LIST cat $FILE | grep -i "\.$EXT" | grep -i "include | grep -vo "\.acm"" >> $MATCH_LIST else cat $FILE | grep -i "\.$EXT" >> $MATCH_LIST cat $FILE | grep -i "\.$EXT" | grep -i "include" >> $MATCH_LIST fi sleep $SLEEP # Replace " = " by "=" sed s/\ =\ /=/ $MATCH_LIST > $MATCH_LIST.2 # Sort list and remove double entries sort $MATCH_LIST.2 | uniq > $MATCH_LIST # Remove trailing 'line feed' character tr -d "\015" < $MATCH_LIST > $MATCH_LIST.2 local NUM_MATCH=`wc -l $MATCH_LIST.2 | awk -F " " '{print $1}'` while read MATCH do printf '\033[6;1H\033[J'"Parsed files\t: $PARSED_COUNT parsed files ($BAD_FILE_COUNT bad)\n" printf '\033[7;1H\033[J'"References\t: $CHECKED_COUNT checked references\n" printf '\033[8;1H\033[J'"Bad references\t: $MISS_COUNT bad refs ($UNIQ_MISS_COUNT uniques)\n" printf '\033[9;1H\033[J'"Corr .geo files\t: $GEO_FILE_COUNT corresponding .geo files (not counted as missing)\n" printf '\033[10;1H\033[J'"Corr .dds files\t: $DDS_FILE_COUNT corresponding .dds files (not counted as missing)\n" printf '\033[11;1H\033[J'"File\t\t: $BASE_FILE\n" printf '\033[12;1H\033[J'"From\t\t: $BASE_FROM\n" printf '\033[13;1H\033[J'"Type\t\t: Text file\n" printf '\033[14;1H\033[J'"Extension\t: $EXT\n" printf '\033[14;23H\033[J'"--> $NUM_MATCH Matching files\n" if [ ${MATCH:0:8} == "#include" ] then ## Action for included file ## # Extract file name from $MATCH local FILE_NAME=`echo $MATCH | awk -F " " '{print $2}'` else ## Action for referenced file ## # Extract file name from $MATCH local FILE_NAME=`echo $MATCH | awk -F "=" '{print $2}'` fi printf '\033[15;1H\033[J'"Found\t\t: $FILE_NAME\n" sleep $SLEEP # Test if file name is absolute or relative if [ ${FILE_NAME:0:1} == "/" ] then printf '\033[16;1H\033[J'"Path type\t: absolute\n" local FILE_NAME=$DATA_DIR$FILE_NAME else printf '\033[16;1H\033[J'"Path type\t: relative\n" local FILE_NAME=$DIR/$FILE_NAME fi sleep $SLEEP load_file $FILE_NAME $FILE done < $MATCH_LIST.2 rm -f $MATCH_LIST rm -f $MATCH_LIST.2 done # $FILE does not exist else # Searching the corresponding .geo file # from ac,X,3DS and lwo files # then count and log it case ${FILE##*.} in ac|AC|3ds|3DS|lwo|LWO|x|X) if [ -f ${FILE%.*}.geo ] then ((GEO_FILE_COUNT++)) echo $FILE >> $GEO_FILE_LOG return fi ;; esac # Searching the corresponding .dds file # from .tga files then count and log it case ${FILE##*.} in tga|TGA|pcx|PCX) if [ -f ${FILE%.*}.dds ] then ((DDS_FILE_COUNT++)) echo $FILE >> $DDS_FILE_LOG return fi ;; esac # Logging missing file echo "$FILE,$FROM" >> $MISS_LOG ((MISS_COUNT++)) # Logging unique missing file # (some missing files are referenced several times # increasing missing files number with no reason) if [ `grep $FILE $UNIQ_MISS_LOG | wc -l` -eq 0 ] then echo "$FILE" >> $UNIQ_MISS_LOG ((UNIQ_MISS_COUNT++)) fi # Files containing bad references are logged only once # even if they have multiple bad references if [ `grep $FROM $BAD_FILE_LOG | wc -l` -eq 0 ] then echo "$FROM" >> $BAD_FILE_LOG ((BAD_FILE_COUNT++)) fi printf '\033[16;1H\033[J'"MISSING\t\t: $FILE\n" printf '\033[17;1H\033[J'"MISSING\t\t: in file\n" printf '\033[18;1H\033[J'"MISSING\t\t: $FROM\n" return fi sleep $SLEEP } function parse_scen_dir { SCEN_DIR=$1 find $SCEN_DIR -type f -print | grep -i '\.scn' > $SCN_LIST while read SCN do SCN_NAME=`basename $SCN` printf '\033[5;1H\033[J'"Scenario file\t: $SCN_NAME\n" sleep $SLEEP load_file $SCN null done < $SCN_LIST } #Display results function report { UNIQ_MISSING=`wc -l $UNIQ_MISS_LOG | awk -F " " '{print $1}'` BAD_FILE_COUNT=`wc -l $BAD_FILE_LOG | awk -F " " '{print $1}'` BAD_FILE_COUNT=`wc -l $BAD_FILE_LOG | awk -F " " '{print $1}'` GEO_FILE_COUNT=`wc -l $GEO_FILE_LOG | awk -F " " '{print $1}'` DDS_FILE_COUNT=`wc -l $DDS_FILE_LOG | awk -F " " '{print $1}'` PARSED_COUNT=`wc -l $PARSED_LOG | awk -F " " '{print $1}'` printf '\033[5;1H\033[J'"$MOD_NAME\t: $PARSED_COUNT parsed files.\n" printf '\033[6;1H\033[J'"$MOD_NAME\t: $CHECKED_COUNT checked references.\n" printf '\033[7;1H\033[J'"$MOD_NAME\t: $MISS_COUNT bad references in $BAD_FILE_COUNT bad files.\n" printf '\033[8;1H\033[J'"$MOD_NAME\t: $UNIQ_MISSING unique missing files.\n" printf '\033[9;1H\033[J'"$MOD_NAME\t: $GEO_FILE_COUNT corresponding .geo files (not counted as missing).\n" printf '\033[10;1H\033[J'"$MOD_NAME\t: $DDS_FILE_COUNT corresponding .dds files (not counted as missing).\n" # Results sorted by estension local I=5; for EXT in ${EXTS[*]} do if [ "$EXT" == "ac" ] then # We only want .ac files, not .acm file local EXT_FILE_NUM=`grep -i "\.$EXT" $UNIQ_MISS_LOG | grep -vi "\.acm" |wc -l | awk -F " " '{print $1}'` else local EXT_FILE_NUM=`grep -i "\.$EXT" $UNIQ_MISS_LOG | wc -l | awk -F " " '{print $1}'` fi printf '\033[J'"$MOD_NAME\t: $EXT\t: $EXT_FILE_NUM missing files.\n" done } function usage { clear printf "Usage : mod_cleaner.sh
\n" printf "i.e : mod_cleaner.sh /home/user/targetware/data tt.mod\n" printf "Other options : \n" printf "mod_cleaner.sh --report (or -r) : Display last report.\n" printf "mod_cleaner.sh --help (or -h) : Display this help.\n" printf "mod_cleaner.sh --version (or -v): Display version.\n" exit } ####################################################################################################################### if [ $# -eq 2 ] then #Remove trailing / if any DATA_DIR=`echo ${1%/}` MOD_FILE=$2 if [ -d $DATA_DIR ] && [ -f $DATA_DIR/$MOD_FILE ] then printf '\033[1;1H\033[J'"TW data dir\t: $DATA_DIR\n" printf '\033[2;1H\033[J'"mod file\t: $DATA_DIR/$MOD_FILE\n" SCEN_DIR=`grep -i scenarios $DATA_DIR/$MOD_FILE | awk -F "=" '{print $2}' | sed -e "s/ //"` SCEN_DIR=`echo $DATA_DIR$SCEN_DIR | tr -d "\015"` MOD_NAME=`grep -i name $DATA_DIR/$MOD_FILE | awk -F "=" '{print $2}' | sed -e "s/ //"` MOD_NAME=`echo $MOD_NAME | tr -d "\015"` printf '\033[3;1H\033[J'"mod\t\t: $MOD_NAME\n" printf '\033[4;1H\033[J'"Scenarios dir\t: $SCEN_DIR\n" if [ -d ${SCEN_DIR} ] then # Here is entry point rm -f $PARSED_LOG $MISS_LOG $SCN_LIST $UNIQ_MISS_LOG $BAD_FILE_LOG $GEO_FILES touch $MISS_LOG $PARSED_LOG $SCN_LIST $UNIQ_MISS_LOG $BAD_FILE_LOG $GEO_FILES parse_scen_dir $SCEN_DIR report else printf '\033[4;1H\033[J'"Scenarios dir $SCEN_DIR is not a valid directory.\n" fi else printf "TW data dir and/or mod file are not valid\n" usage exit fi elif [ $# -eq 1 ] then case $1 in --report|-r) printf '\033[1;1H\033[J'"*******************************************************\n" printf '\033[2;1H\033[J'"* This report is generated from existing log files. *\n" printf '\033[3;1H\033[J'"* Warning, this may be inconsistent and/or incomplete. *\n" printf '\033[4;1H\033[J'"*******************************************************\n" report ;; --version|-v) printf "mod_cleaner.sh, version 1.0-rc2 \n" printf "Send comment or bug report to :\n" printf "doug.letough@free.fr\n" printf "(C) 2009 - Doug Le Tough\n" ;; --help|-h) usage ;; *) usage ;; esac else usage fi