Aide sur la commande script / rsync pour déplacer le fichier avec la comparaison de somme md5 avant de supprimer le fichier source / [fermé]

1

Référencement de ce post to find et supprimer les fichiers en double en fonction de la somme de contrôle , j'aimerais modifier l'approche pour effectuer une opération de copie suivie d'une vérification de l'intégrité du fichier de destination.

SOURCE = /path/to/Source
DEST = /path/to/Destination
# filecksums containing the md5 of the copied files
declare -A filecksums

for file in "[email protected]"
do
    [[ -f "$file" ]] || continue

    # Generate the checksum
    cksum=$(cksum <"$file" | tr ' ' _)

    # Can an exact duplicate be found in the destination directory?
    if [[ -n "${filecksums[$cksum]}" ]] && [[ "${filecksums[$cksum]}" != "$file" ]]
    then
        rm -f "$file"
    else
        echo " '$file' is not in '$DEST'" >&2
    fi
done

Je souhaite utiliser le résultat de la comparaison de somme de contrôle md5 pour autoriser rm -f du fichier source uniquement si les sommes de contrôle sont équivalentes. S'il y a une différence, je veux faire écho au résultat et m'échapper. rsync pourrait être une autre option, mais je pense que je ne pourrais pas forcer une comparaison de somme de contrôle pour le transfert de fichiers local-local.

MISE À JOUR J'ai envisagé d'utiliser rsync pour la réponse de @Lucas. Il semble qu’il existe des options pour transférer les fichiers de manière plus stable avec des contrôles plutôt qu’une masse mv /data1/* /data2/ et signaler ce qui a été fait et les supprimer après un contrôle. Cela pourrait affiner la définition indiquée par les membres de la communauté.

    
posée brawny84 10.07.2018 - 20:25
la source

1 réponse

1

Implémenter quelque chose comme ceci peut être difficile du premier coup si vous vous souciez des fichiers et que vous ne voulez pas vous perdre. Voici donc quelques alternatives à l'écriture d'un script complet en bash. Ce sont des lignes de commande plus ou moins complexes qui pourraient vous aider dans votre situation.

Il y a une incertitude dans votre question: voulez-vous comparer chaque fichier dans la source avec tous les fichiers dans la destination ou uniquement ceux avec des noms de fichier "correspondants"? (Ce serait comparer /path/to/src/a avec /path/to/dest/a et /path/to/src/b avec /path/to/dest/b mais pas /path/to/src/a avec /path/to/dest/b et ainsi de suite)

Je suppose que vous souhaitez uniquement comparer les fichiers avec des chemins correspondants!

première idée: diff

Le bon vieux diff peut comparer les annuaires de manière récursive. Utilisez également l’option -q pour voir quels fichiers sont différents et non comment ils se différencient.

diff -r -q /path/to/source /path/to/dest

contre

  • Cela peut prendre longtemps en fonction de la taille de votre disque dur.
  • Cela ne supprime pas les anciens fichiers.
  • La sortie n'est pas facilement analysable

pros

  • Ceci ne supprime aucun fichier:)

Ainsi, après avoir confirmé manuellement / visuellement qu'il n'y a pas de différences dans les fichiers qui vous intéressent, vous devez supprimer manuellement la source avec rm -rf /path/to/source .

deuxième idée: rsync (edit: cela pourrait être le meilleur maintenant)

rsync est le maître de tous les outils de copie en ligne de commande (à mon avis;). Comme mentionné dans les commentaires de votre question, il existe une option --checksum , mais il contient également d'autres options. Il peut transférer des fichiers de local à distant, de distant en local et de local à local. Une des caractéristiques les plus importantes à mon avis est que si vous donnez les options correctes, vous pouvez abandonner et relancer la commande (exécuter à nouveau la même ligne de commande) et elle continuera là où elle est restée!

Pour ce faire, les options suivantes peuvent être intéressantes:

  • -v : verbose, montre ce qui se passe peut être donné plusieurs fois mais normalement, cela suffit
  • -n : piste sèche, très important de tester des choses mais ne rien faire (à combiner avec -v ) !!
  • -c : utilisez la somme de contrôle pour décider de ce qui doit être copié
  • --remove-source-files : supprime les fichiers transférés avec succès (signalé par @ brawny84, je ne le savais pas et je ne le trouvais pas dans la page de manuel de ma première lecture)

Ainsi, cette commande écrasera tous les fichiers de dest dont le total de contrôle est différent de celui du fichier correspondant de source (correspondant à leur nom).

 rsync -a -c -v --remove-source-files -n /path/to/source /path/to/dest
 rsync -a -c -v --remove-source-files    /path/to/source /path/to/dest

pros

  • fonctionne avec les sommes de contrôle
  • a un mode de fonctionnement à sec
  • va réellement copier tous les fichiers manquants et ceux qui diffèrent d'une source à l'autre
  • peut être abandonné et redémarré
  • a une option d'exclusion pour ignorer certains fichiers de src si vous ne voulez pas copier tous les fichiers
  • peut supprimer les fichiers source transférés

contre

  • ??

troisième idée: fdupes

Le programme fdupes a été conçu pour répertorier les fichiers en double. Il vérifie les sommes md5 par défaut.

pros

  • il utilise md5 pour comparer les fichiers
  • il a une option --delete pour supprimer l’un des doublons

contre

  • il compare chaque fichier à un autre fichier , donc s'il y a des fichiers en double à l'intérieur de la destination elle-même, il les listera également
  • le mode de suppression semble être interactif, vous devez confirmer pour chaque ensemble de fichiers égaux, ce qui pourrait ne pas être réalisable pour les arborescences de répertoires volumineuses
  • le mode non interactif supprimera tout, sauf le premier fichier, de chaque ensemble de fichiers égaux. Mais je ne sais pas du tout quel est le premier fichier (en source ou en destination?)

Dernière idée: passer à travers la douleur d’écrire et de déboguer votre propre script shell

Je commencerais par quelque chose comme ceci si cela doit être fait manuellement. Je n'ai pas testé cela, essayez-le d'abord avec le ls et essayez de savoir s'il freine quelque chose !!

#!/bin/bash
# first require that the source and dest dirs
# are given as arguments to the script.
src=${1:?Please give the source dir as first argument}
dest=${2:?Please give the destination dir as second argument}
# go to the source directory
cd "$src"
# This assumes that there are no newlines in filenames!
# first find all plain files in the current dir 
# (which should be $src)
# then use xargs to hand the filenames to md5sum 
# pipe the md5 sums into a subshell
# go to the dest in the subshell
# read the md5sums from stdin and use md5sum -c to check them 
# After the subshell filter lines to only keep those that end in "OK"
# and at the same time remove the "OK" stuff after the file name
# use xargs to hand these file names to ls or rm.
find . -type f | \
  xargs md5sum | \
  ( cd "$dest" && md5sum -c ) | \
  sed -n 's/: OK$//p' | \
  xargs ls

Le ls de la dernière ligne doit répertorier tous les fichiers qui ont réussi la vérification. Si vous le remplacez par rm , ils sont supprimés du répertoire source (le répertoire actuel après le cd "$src" ).

    
réponse donnée 10.07.2018 - 22:05
la source

Lire d'autres questions sur les étiquettes