#!/bin/bash

# Fichier : script2.sh
# Auteur  : Florent Devin <florent.devin@eisti.fr>
# Version : 1.0
# Date    : 23 novembre 2009
# Description : Script qui permet de déplacer ou supprimer des fichiers en double


NOCRC=0
REP=""

# Fonction : usage
# Auteur   : Florent Devin <florent.devin@eisti.fr>
# Version  : 1.0
# Date     : 23 novembre 2009
# Description : Affiche l'aide, et quitte avec un code d'erreur si passé en paramètre
usage () {
	echo "Usage : doublon [OPTION] [REPERTOIRE]"
	echo "doublons : script de détection et de suppression des doublons"
	echo "Sans REPERTOIRE, applique le script sur le répertoire courant."
	echo "  -h, --help  affiche cette aide, et quitte"
	echo "  -d          efface les doublons détectés"
	echo "  -o rep      déplace les doublons détectés dans rep"
	echo "  --no-crc    ne calcule pas le CRC pour déterminer les doublons"
	if [ $# -gt 0 ]
	then
		exit $1
	fi
}

# Fonction : traite_argument
# Auteur   : Florent Devin <florent.devin@eisti.fr>
# Version  : 1.0
# Date     : 23 novembre 2009
# Description : Fonction qui traite les arguments de la ligne de commande et qui identifie les options passé
# Remarque    : Cette fonction détecte si on utilise une option qui n'est pas prévue, et affiche l'aide
#             : Par ailleurs pour que le script fonctionne il faut avoir spécifié soit -d soit -o rep
#             :   Si on a spécifié -o, on s'assure que l'argument suivant est bien un répertoire, et qu'on a les drtois d'écriture
traite_argument () {
	while [ $# -gt 0 ]
	do
		case "$1" in
			"-h" | "--help")
				usage 0;;
			"--no-crc")
				NOCRC=1;;
			"-d")
			if [ -z "${OK}" ]
					then
					OK=1
			else
					echo "Vous ne pouvez utiliser simultanément -d et -o"
					usage 1
			fi;;
			"-o" )
			if [ ! -z "${OK}" ]
					then
					echo "Vous ne pouvez utiliser simultanément -d et -o"
					usage 1
			fi
			if [ ! -z "$2" ]
					then
					OK=2
					if [ -d "$2" -a -w "$2" ]
							then
							REP=$2
					else
							echo "$2 n'est pas un répertoire accessible en ecriture"
							usage 2
					fi
					shift
			else
					echo "Répertoire manquant pour l'option -o"
					usage 1
			fi;;
			
			*) # Ici on est dans le cas par défaut.
			# On va donc tester si on est sur le dernier paramètre
			if [ $# -eq 1 ]
					then
					# Si c'est le cas alors on vérifie que ce paramètre est bien un répertoire
					if [ -d $1 ]
							then
							if [ -z "${OK}" ]
							then
									OK=1
							fi
							COURANT=$1
					else
							echo "Option non reconnue : $1"
							usage 1
					fi
			else
					# Si on est pas sur le dernier paramètre, la syntaxe de
					# la commande n'est pas respctée.
							echo "Option non reconnue : $1"
							usage 1
			fi;;
		esac;
		shift;
	done;
}


# Fonction : crc_check
# Auteur   : Florent Devin <florent.devin@eisti.fr>
# Version  : 1.0
# Date     : 23 novembre 2009
# Description : Calcule le CRC sur les fichiers passé en paramètre
#               Renvoie ce calcul dans un fichier sous forme MD5:CRC FILE
crc_check () {
		while [ $# -gt 0 ] 
			do
			MD5=$1
			FILE=$2
			CRC=`jacksum $2 | cut -f 1 -d ' '`
			shift
			shift
			echo "${MD5}:${CRC} ${FILE}" >> ${CRC_CHECK}
		done
		
}



# On traite la ligne de commande
traite_argument $*

# S'il n'y a pas eu l'option -d ou -o de spécifier
# Il manque un paramètre. Donc on affiche l'aide
if [ -z "${OK}" ]
then
		echo "Paramètre manquant"
		usage 1
fi

#Maintenant on va pouvoir traiter les doublons. On calcule tous les md5
# La version proposée ici, est une version totalement "inoptimisée".
# On aurait pu proposer une version différente, mais les compétences demandées
#   depassent le cadre de ce cours
TEMP=`mktemp`
MD5_DOUBLE=`mktemp`
FICHIER_DOUBLE=`mktemp`
CRC_CHECK=`mktemp`

# On utilise la commande find pour n'avoir que des fichiers.
find ${COURANT} -type f -maxdepth 1 2>/dev/null | while read ligne
do
	md5sum "${ligne}" >> ${TEMP}
done

#On extrait tous les MD5 en double
sort ${TEMP} | uniq -D -w 32 > ${FICHIER_DOUBLE}

cut -d ' ' -f 1 ${FICHIER_DOUBLE} > ${MD5_DOUBLE}

# Pour chaque MD5 on va éventuellement vérifier son CRC
if [ ${NOCRC} -eq 0 ]
then
		# On ne calcule le CRC que sur les fichiers en double
		uniq -d -w 32 ${MD5_DOUBLE} | while read ligne
			do
			crc_check `grep "${ligne}" ${TEMP}`
		done
else
		rm -f ${CRC_CHECK}
		CRC_CHECK=${FICHIER_DOUBLE}
fi

#Maintenant il ne reste plus qu'à extraire les fichiers 
# et à les effacer, ou les bouger selon l'option
OLD=""
while read ligne
do
	FICHIER=${ligne#* }
	VALEUR=${ligne% *}
	if [ "${OLD}" = "${VALEUR}" ]
			then
			if [ $OK -eq 1 ]
			then
					echo "rm ${FICHIER}"
			else
					echo "mv ${FICHIER} ${REP}" 
			fi
			else
			OLD=${VALEUR}
	fi
done < ${CRC_CHECK}


#Une fois ceci fait, on efface les fichiers temporaires
rm -f ${TEMP} ${MD5_DOUBLE} ${FICHIER_DOUBLE} ${CRC_CHECK}
