Gibt es eine Möglichkeit, Duplikate raffinierter zu löschen als mit fdupes -rdN?

Gibt es eine Möglichkeit, Duplikate raffinierter zu löschen als mit fdupes -rdN?

In letzter Zeit muss ich viele Duplikate löschen. Ich füge drei oder vier Dateisysteme zusammen und möchte den Speicherplatz wirtschaftlich nutzen. Zunächst fdupesschien es das beste Tool für diese Aufgabe zu sein, aber ich stoße zunehmend an Grenzen.

Betrachten Sie den Befehl fdupes -rdN somedirectory/. Dadurch wird ein Hash aller Dateien in den Unterverzeichnissen von somedirectory erstellt.

Und wenn es auf Duplikate stößt, löscht es diese, sodass von allem nur eine Kopie vorhanden ist.

Aber was, wenn ich behalten möchte somedirectory/subdirectory1/somefileund es tatsächlich vier Duplikate gibt und das Programm zuerst auf eines der Duplikate stößt? Dann löscht es somedirectory/subdirectory1/somefile, was ich nicht möchte.

Ich möchte irgendwie angeben können, welche Duplikate behalten werden sollen. Und bisher scheint keines der Standardprogramme zum Umgang mit Duplikaten (duff, FSLint) die Automatisierung dieser Art von Verhalten zu ermöglichen. Ich möchte lieber kein eigenes Programm entwickeln, deshalb stelle ich diese Frage.

Ich würde gerne so etwas schreiben können wie

killdupes -rdN --keep=filesin,somedirectories,separated,by,commas somedirectory/

Antwort1

Da die von Ihnen gesuchte Funktionalität nicht auf Lager ist fdupes, habe ichfdupes (meine Gabel heißt jdupes)und einige Features hinzugefügt, die dieses Problem unter bestimmten Umständen lösen können. Im angegebenen Fall, in dem Sie beispielsweise somedirectory/subdirectory1/somefilebeim automatischen Löschen Duplikate beibehalten möchten (die Schalter dund Nzusammen) und sich keine separaten Dateien direkt darunter befinden somedirectory, jdupeskönnen Sie jeden unmittelbaren Unterverzeichnispfad subdirectory1zuerst mit dem Schalter und dem -OSchalter (der Dateien zuerst nach der Reihenfolge der Befehlszeilenparameter sortiert) füttern:

jdupes -rdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3

Dadurch werden alle Dateien bis auf eine in einem Duplikatssatz automatisch gelöscht. Außerdem wird garantiert, dass, wenn der Satz eine Datei enthält, somedirectory/subdirectory1diese die erste ist und somit automatisch zur beibehaltenen Datei im Satz wird. Dieser Ansatz hat immer noch eklatante Einschränkungen, wie etwa die Tatsache, dass somedirectory/subdirectory1möglicherweise ein anderes Duplikat beibehalten wird, anstatt das, das Sie behalten wollten. In vielen Fällen wie Ihrem jdupesist die Option der Parameterreihenfolge als Workaround jedoch ausreichend.

In naher Zukunft plane ich, ein Filtersystem hinzuzufügen, jdupesdas eine umfassende Kontrolle über die Einbeziehung/den Ausschluss von Dateien, die Beibehaltung für -NAktionen und die Anwendung solcher „Filterstapel“ entweder global oder pro Parameter ermöglicht. Diese Funktion wird dringend benötigt; ich stelle mir so etwas vor, um „Duplikate ungleich Null rekursiv automatisch zu löschen, ABER immer so zu erhalten, somedirectory/subdirectory1/somefilewie sie sind“:

jdupes -rdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/

UPDATE (01.03.2022):Schauen Sie sich die -Xerweiterten Filteroptionen an, die im Jahr 2020 hinzugefügt wurden. Es ist nicht genau das, was Sie wollen, aber mit den - nostrund onlystr-Filtern können Sie Teilzeichenfolgen innerhalb eines vollständigen Pfads angeben, die ignoriert oder angefordert werden sollen.

Antwort2

Das habe ich nirgendwo sonst gesehen: Sagen Sie, was Sie wollen, ist Folgendes. Sie haben /mnt/Ordnerbaum-1 /mnt/Ordnerbaum-2. Sie wollen nicht jeden Duplikat entfernen, aber wenn eine Datei in Baum-2 existiert und eine identische Datei in Baum-1 mit genau demselben Pfad und Namen existiert, entfernen Sie sie aus Baum-2.

Achtung: Dies ist ziemlich knapp gehalten, und seien Sie vorsichtig, wenn Sie versuchen, es mit begrenzten Shell-Kenntnissen zu kopieren und einzufügen.

fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt

fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line
do
if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt
then
    echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2//|')\"
fi
done > rm-v2-dupes.sh

Oder alles in einer Zeile:

fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt; fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line; do if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt; then echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|')\"; fi; done > rm-v2-dupes.sh

Anschließend überprüfen und führen Sie rm-v2-dupes.sh aus.

Antwort3

Wie wäre es, die doppelten Dateien fest miteinander zu verknüpfen? Auf diese Weise wird der Speicherplatz nur einmal verwendet, aber sie sind immer noch in allen Pfaden vorhanden. Der Haken dabei ist, dass fest verknüpfte Dateien an Ort und Stelle geändert werden sollten (sie sollten nur geändert werden, indem die Datei gelöscht und mit dem neuen Inhalt neu erstellt wird). Der andere Ansatz besteht darin, die Dateien symbolisch miteinander zu verknüpfen, obwohl Sie das gleiche Problem haben, zu entscheiden, welche die „primäre“ Datei ist. Dies könnte mit dem folgenden Skript erfolgen (beachten Sie jedoch, dass dies keine Dateinamen mit Leerzeichen verarbeitet).

fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do
    for DEST in $DESTS; do
        ln -f $SOURCE $DEST
    done
done

Antwort4

Nur um einer vorherigen Antwort eine Wendung zu geben. Ich habe den folgenden Code mehrmals verwendet und eine vorherige Antwort leicht modifiziert, um | grepden Ordner, aus dem ich löschen möchte, einfach zu isolieren.

`fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`

Auch hier wird eine SH-Datei erstellt, um alle aufgelisteten Dateien zu löschen, keine auskommentierten Zeilen. Natürlich können Sie die Datei weiterhin bearbeiten, um bestimmte Zeilen/Dateien, die Sie behalten möchten, auskommentieren.

Ein weiterer Tipp für große Verzeichnisse besteht darin, fdupes in einer TXT-Datei auszuführen und dann damit zu experimentieren, | grepbis | sedich das gewünschte Ergebnis erhalte.

`fdupes -r -n -S /directory > duplicate-files.txt`
`cat duplicate-files.txt | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`

verwandte Informationen