Doppelte Dateien löschen
Script zum rekursiven löschen doppelter Dateien in einem Verzeichnis. Hierbei werden die in einem Verzeichnis vorhandenen doppelten Dateien in ein anderes Verzeichnis verschoben.
Beschreibung
Bei der Anwendung dieses Scripts muss es egal sein, welche der doppelten Dateien behalten wird. Hierbei geschieht das Löschen indirekt, indem doppelte Dateien ins Verzeichnis BACKUP verschoben werden, welches dann manuell gelöscht werden muss. Doppelte Dateien werden anhand ihres MD5-Hash gefunden und Dopplungen nochmal byte-genau verglichen, bevor sie aussortiert werden. Der Weg über den Hash ist schneller als das direkte Vergleichen der Dateien. Das Skript sollte hierbei auch richtig auf Hash-Kollisionen reagieren, da alle Dateien mit dem selben Hash nochmal byte-genau auf Dopplungen überprüft werden.
Code
Hinweis: So blöd es auch klingt: MACH DIR EIN BACKUP VON DEM DATEIEN-HAUFEN! |
#!/bin/sh
# doppelte Dateien verschieben/löschen
#
# BENUTZUNG: sh Pfad/zum/Skript.sh AUFRÄUMEN BACKUP
#
# Backup-Verz. ggf. anlegen und auf Schreibrechte prüfen
mkdir -p "$2" && [ -w "$2" ] || exit
# MD5-Hashes aller Dat. erzeugen; Leere auslassen
all=$(mktemp)
find "$1" -type f ! -empty -exec md5sum "{}" \; | tee $all || exit
# doppelte Dat. auflisten
dbl=$(mktemp)
cut -b 1-32 $all | sort | uniq --repeated | while read n; do
grep "^$n" $all | cut -b 34- | while read m; do
echo "$n $m" >> $dbl
done
echo "#NEW-DATASET####################" >> $dbl
done
# doppelte Dat. verschieben/löschen
md5=$(mktemp)
cat $dbl | while read n; do
if [ $(echo "$n" | cut -b 1-32) != "#NEW-DATASET####################" ]; then
echo "$n" | cut -b 34- >>$md5
else
cat $md5 | while read u; do
[ ! -e "$u" ] && continue
cat $md5 | while read f; do
[ ! -e "$f" -o "$f" = "$u" ] && continue
# Wenn die Dateien (noch) existieren und die Pfade
# unterschiedlich sind, byte-genaue Kopien verschieben/löschen
cmp --quiet "$u" "$f" && mv -v --backup=numbered --target-directory="$2" "$f"
done
done
echo >$md5
fi
done
rm $all $dbl $md5
# leere Dat. und Verz. löschen
#find "$1" -depth -empty -delete