Comment supprimer les fichiers en double à l'aide de bash

10

J'ai un dossier avec des fichiers en double (par md5sum( md5sur un Mac)) et je veux avoir un tâche planifiée pour supprimer tout élément trouvé.

Cependant, je suis coincé sur la façon de procéder. Ce que j'ai jusqu'à présent:

md5 -r * | sort

Qui génère quelque chose comme ceci:

04c5d52b7acdfbecd5f3bdd8a39bf8fb gordondam_en-au11915031300_1366x768.jpg
1e88c6899920d2c192897c886e764fc2 fortbourtange_zh-cn9788197909_1366x768.jpg
266ea304b15bf4a5650f95cf385b16de nebraskasupercell_fr-fr11286079811_1366x768.jpg
324735b755c40d332213899fa545c463 grossescheidegg_en-us10868142387_1366x768.jpg
3993028fcea692328e097de50b26f540 Soyuz Spacecraft Rolled Out For Launch of One Year Crew.png
677bcd6006a305f4601bfb27699403b0 lechaustria_zh-cn7190263094_1366x768.jpg
80d03451b88ec29bff7d48f292a25ce6 ontariosunrise_en-ca10284703762_1366x768.jpg
b6d9d24531bc62d2a26244d24624c4b1 manateeday_row10617199289_1366x768.jpg
ca1486dbdb31ef6af83e5a40809ec561 Grueling Coursework.jpg
cdf26393577ac2a61b6ce85d22daed24 Star trails over Mauna Kea.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x768.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x7682.jpg

Comment puis-je traiter en fonction du MD5 du fichier pour supprimer les doublons? Peu m'importe quel "original" je garde - mais je veux seulement en garder un.

Dois-je aborder cela d'une manière différente?

garenne
la source
3
Il y a déjà une fdupescommande qui fera ça ... Je ne sais pas sur quelle distribution vous vous trouvez, mais c'est dans un paquet Debian du même nom. De plus, MD5 est un hachage assez faible de nos jours; vous voulez probablement utiliser sha256sum ou mieux sha512sum(qui devrait en fait être plus rapide sur le matériel PC normal)
derobert
1
@derobert - Je sais que MD5 est un hachage faible, mais c'est simple et assez bon pour comparer de petits fichiers :)
warren
eh bien, les collisions MD5 sont connues et générables avec des quantités assez modestes de puissance CPU, et il y a une commande que vous pouvez remplacer pour utiliser SHA-512 à la place, alors ...
derobert
@derobert - Je comprends qu'il y a des inconvénients potentiels à utiliser md5 .. mais c'est plus que suffisant dans ce scénario (je veux m'assurer que je n'ai pas de fichiers en double dans un répertoire donné)
warren
1
C'est suffisant. Le point principal du commentaire était de signaler les fdupes.
derobert

Réponses:

3

Je travaille sur Linux, ce qui signifie que la commande est la md5sumsortie:

> md5sum *
d41d8cd98f00b204e9800998ecf8427e  file_1
d41d8cd98f00b204e9800998ecf8427e  file_10
d41d8cd98f00b204e9800998ecf8427e  file_2
d41d8cd98f00b204e9800998ecf8427e  file_3
d41d8cd98f00b204e9800998ecf8427e  file_4
d41d8cd98f00b204e9800998ecf8427e  file_5
d41d8cd98f00b204e9800998ecf8427e  file_6
d41d8cd98f00b204e9800998ecf8427e  file_7
d41d8cd98f00b204e9800998ecf8427e  file_8
d41d8cd98f00b204e9800998ecf8427e  file_9
b026324c6904b2a9cb4b88d6d61c81d1  other_file_1
31d30eea8d0968d6458e0ad0027c9f80  other_file_10
26ab0db90d72e28ad0ba1e22ee510510  other_file_2
6d7fce9fee471194aa8b5b6e47267f03  other_file_3
48a24b70a0b376535542b996af517398  other_file_4
1dcca23355272056f04fe8bf20edfce0  other_file_5
9ae0ea9e3c9c6e1b9b6252c8395efdc1  other_file_6
84bc3da1b3e33a18e8d5e1bdd7a18d7a  other_file_7
c30f7472766d25af1dc80b3ffc9a58c7  other_file_8
7c5aba41f53293b712fd86d08ed5b36e  other_file_9

Maintenant, utiliser awket xargsla commande serait:

md5sum * | \
sort | \
awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | \
xargs rm

La awkpartie s'initialise lasthashavec la chaîne vide, qui ne correspondra à aucun hachage, puis vérifie pour chaque ligne si le hachage dans lasthashest le même que le hachage (première colonne) du fichier en cours (deuxième colonne). Si c'est le cas, il l'imprime. À la fin de chaque étape, il sera défini lasthashsur le hachage du fichier actuel (vous pouvez limiter cela à seulement si les hachages sont différents, mais cela devrait être une chose mineure surtout si vous n'avez pas beaucoup de fichiers correspondants). Les noms de fichiers awk crachent sont alimentés rmavec xargs, ce qui appelle essentiellement rmavec ce que la awkpartie nous donne.

Vous devez probablement filtrer les répertoires avant md5sum *.

Éditer:

En utilisant la méthode Marcins, vous pouvez également utiliser celle-ci:

comm -1 -2 \
  <(ls) | \
  <(md5sum * | \
    sort -k1 | \
    uniq -w 32 | \
    awk '{print $2}' | \
    sort) \
xargs rm

Cela soustrait la liste de fichiers choisie par lsle premier nom de fichier de chaque hachage unique choisi par md5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'.

Tristan Storch
la source
1
merci: md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rmc'est l'appel sur OS X (selon la suggestion de @ Stephen Kitt , j'ai mis un echo 'will remove 'à la fin avant de l'essayer avec rm)
warren
Vous devriez alors probablement modifier votre question car la solution donnée ne correspond pas à l'exemple de sortie que vous avez donné.
Stephen Kitt
1
Et vous devriez changer sort -t ' ' -k 4 -rpour sort.
Tristan Storch
@TristanStorch - bon endroit :)
warren
Cela suppose que vous n'avez aucun espace dans vos noms de fichiers, hypothèse dangereuse en toutes circonstances. (Et d'autant plus que l'OP utilise un Mac. Je vous défie de trouver un Mac, n'importe quel Mac, qui n'a aucun nom de fichier contenant de l'espace.) :)
Wildcard
7

Vous pouvez identifier les fichiers en double à l'aide de la commande suivante:

md5sum * | sort -k1 | uniq -w 32 -d
Marcin
la source
1
Cela ne génère qu'un seul fichier pour chaque ensemble de doublons. Si vous souhaitez supprimer tous les doublons et n'en conserver qu'un, vous pouvez conserver ceux que vous obtenez avec cette commande et supprimer le reste
golimar
2

J'ai rencontré fdupes en réponse à cette question similaire: /superuser/386199/how-to-remove-duplicated-files-in-a-directory

J'ai pu le faire apt-get install fdupessur Ubuntu. Vous voudrez certainement lire la page de manuel. Dans mon cas, j'ai pu obtenir les résultats souhaités comme suit:

fdupes -qdN -r /ops/backup/

Qui dit "regardez récursivement dans / ops / backup et trouvez tous les fichiers en double: conservez la première copie d'un fichier donné et supprimez tranquillement le reste". Cela permet de conserver très facilement plusieurs vidages d'une base de données à écriture peu fréquente.

dannyman
la source
1

Si vous êtes pressé (ou si vous avez beaucoup de fichiers) et que vous voulez éviter les frais généraux d'une sorte (cela prend du temps), mais ne vous occupez pas de la surcharge de mémoire d'une table de hachage (ou vous avez beaucoup de RAM avec vos lots de fichiers),

find . -type f -print0 | xargs -0 md5sum | awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }' | xargs -0 rm

find . -type f -print0: Rechercher tous les fichiers et les afficher avec des noms se terminant par null

xargs -0 md5sum: calculer les hachages en parallèle (ajustez -nmax-args et -Pmax-procs comme vous le souhaitez, voir man xargs)

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }': s'il y a une entrée dans la table de hachage awk contenant la somme md5 que nous regardons actuellement, alors imprimez le nom de fichier que nous regardons actuellement, terminé par null. Sinon, ajoutez le nom de fichier à la table de hachage.

xargs -0 rm: prenez les chaînes terminées nulles et envoyez-les à rm.

C'est bien plus rapide que fdupes.

Si vous avez un nom de fichier qui contient une nouvelle ligne, awk le tronquera probablement sur la nouvelle ligne car md5sum sépare également les enregistrements par des nouvelles lignes.

Ceci est basé sur /programming/11532157/remove-duplicate-lines-without-sorting et /programming/9133315/how-can-i-output-null-terminated- cordes en awk

Alex
la source
1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. prendre toutes les valeurs md5
  2. les trier pour que les dupes soient séquentielles pour uniq
  3. exécuter uniq pour sortir uniquement les dupes
  4. couper le nom de fichier de la ligne avec la valeur md5
  5. appeler à plusieurs reprises supprimer sur les noms de fichiers
Carter Cole
la source
0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

Fonctionnalités:

  • Fonctionne toujours s'il y a plus d'un doublon par fichier
  • Fonctionne toujours si les noms de fichiers ont des espaces
  • Fonctionne toujours si vous avez un alias lsavec un tri ou--color=always
Alex Lamson
la source