Doppelte Dateien löschen

Aus DebianforumWiki
Zur Navigation springen Zur Suche springen
Wiki ‹ Scripting ‹ 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.png 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