Meilleure pratique pour continuer mv

13

J'ai utilisé le terminal pour copier des fichiers d'un lecteur à un autre.

sudo mv -vi /location/to/drive1/ /location/to/drive2/

Cependant, cela s'est soudainement arrêté, pendant quelques heures, et sans erreur, après la création d'un répertoire.

Ma propre solution à cela est souvent un mélange de hachage et de comparaison, ce qui est surtout un gâchis qui prend du temps car je dois maintenant récupérer à partir d'une copie intermédiaire sans vraiment savoir quels fichiers sont manquants (écrits comme une très longue ligne pour zsh - notez que ce script ne fonctionne pas en bash comme écrit):

source_directory="/path/to/source_directory/";
target_directory="/path/to/target_directory/";
while read hash_and_file; do {
    echo "${hash_and_file}" | read hash file;
    echo "${file}" | sed "s/^/${source_directory}/g" | read copy_from;
    echo "${copy_from}" | sed "s/${source_directory}/${target_directory}/g" | read copy_to;
    mv -v "${copy_from}" "${copy_to}" | tee -a log;
    rm -v "${copy_from}" | tee -a log; };
done <<<$(
    comm -23 <( find ${source_directory} -type f -exec sha256sum "{}" \; |
                sed "s: ${source_directory}: :g" | sort;
           ) <( find ${target_directory} -type f -exec sha256sum "{}" \; |
                sed "s: ${target_directory}: :g" | sort; ) )

Ceci est sujet aux erreurs si le nom du répertoire cible ou du répertoire source fait partie du chemin d'accès et supprime les fichiers s'ils n'ont pas été déplacés car ils ont été marqués comme doublons. De plus, il ne source pas le répertoire à la fin.

Existe-t-il une meilleure pratique pour récupérer d'un mv interrompu?

Quoi
la source
J'ai écrit un script similaire , qui utilise cmpau lieu de hacher. Il a des dépendances, et les mêmes problèmes while readque ceux mentionnés par Gilles. Il est également lent et verbeux. Mais cela libère de l'espace disque plus tôt que la méthode rsync, car les fichiers sont (re) déplacés de la source pendant son exécution. Il peut servir d'inspiration aux courageux.
joeytwiddle
3
@joeytwiddle rsync offres --delete-during receiver deletes during the transferet aussi plusieurs autres alternatives utiles: --delete --delete-before --delete-delay --delete-after --delete-excluded. Donc, oui, rsync est la meilleure alternative,
Isaac
J'ai dû louper quelque chose. Pourquoi ne pas répéter la même mvcommande ne fonctionne-t-il pas? Peut-être avec *ajouté au chemin source si la source d'origine était un répertoire.
jpa
@isaac Non, je crains que ce rsync --delete*ne soit un désastre ! Il supprimera les éléments destqui ne sont pas actuellement dans src, donc tous les fichiers qui ont été déplacés avec succès lors de la tentative précédente seront désormais supprimés! Vous pensiez probablement à rsync --remove-source-filesce que je suis d'accord serait une bonne alternative. ( more1 , more2 )
joeytwiddle
@joeytwiddle Non, rsync --deleteva seulement supprimer d' autres fichiers qui ne font pas partie de la source. De [man rsync] () * supprimez les fichiers superflus des répertoires dest *. Comprenez ce que signifie étranger : ne pas être synchronisé. Et oui, rsync fournit également un moyen de supprimer les fichiers source après qu'ils ont été correctement transmis.
Isaac

Réponses:

46

Oubliez d'essayer de réinventer rsync et utilisez rsync.

sudo rsync -av /location/to/drive1/ /location/to/drive2/

Assurez-vous d'utiliser une barre oblique de fin sur la source, sinon elle serait copiée vers /location/to/drive2/drive1.

Vérifiez que la commande a réussi, puis exécutez rm -rf /location/to/drive1/.

La commande ci-dessus écrasera tout fichier préexistant de drive2. Si vous souhaitez inviter l'utilisateur à ignorer les fichiers qui existaient déjà dans drive2, comme avec mv -i, c'est plus compliqué, car vous devez maintenant distinguer les fichiers qui ont déjà été copiés et les fichiers qui n'en ont pas. Vous pouvez passer l' --ignore-existingoption à rsync pour ignorer les fichiers qui existent déjà sur la destination quel que soit leur contenu. Notez que si l'original a mvété interrompu au milieu de la création d'un fichier, ce fichier restera dans son état semi-copié (alors qu'un nu rsync -aterminerait correctement sa copie).

Si vous souhaitez reproduire le comportement exact de mv -i, y compris l'invite, cela pourrait être fait, mais c'est beaucoup plus compliqué.

Notez que votre doublure géante est très fragile. S'il existe des noms de fichiers contenant des barres obliques inverses ou des sauts de ligne, ils peuvent ne pas être copiés correctement ou ils peuvent même inciter votre script à supprimer des fichiers arbitraires. N'utilisez donc pas le code de la question, sauf si vous êtes sûr de pouvoir faire confiance aux noms de fichier pour ne pas contenir de barres obliques inversées ou de nouvelles lignes.

Pour référence future, je recommande de ne jamais l'utiliser mvpour les grands mouvements cross-drive, précisément parce qu'il est difficile de contrôler ce qui se passe s'il est interrompu. Utilisez rsync pour effectuer la copie, puis retirez l'original.

Gilles 'SO- arrête d'être méchant'
la source
Quelles promesses fait rsync que mv ne fait pas?
Que
4
eh bien, par exemple rsyncfait ce que vous essayez de faire, alors mvque non. Aussi: copie entre différentes machines; compression pour le transfert; ignorer les fichiers existants à la destination en fonction de l'égalité basée sur l'horodatage ou le hachage; gestion configurable de la propriété, des autorisations, des liens et des fichiers spéciaux; etc. linux.die.net/man/1/rsync
Silly Freak
1
@SillyFreak devrais-je en conclure que je devrais toujours utiliser rsync au lieu de mv, non seulement comme Gilles l'a dit pour le cross-drive, mais pour toute opération, car la limite de "trop ​​grand" est relativement subjective et en cas de problème cela aurait été résolu par rsync de toute façon?
Que
9
eh bien, lorsque je déplace des fichiers ou des répertoires dans une partition, j'utilise généralement mv(ou le gestionnaire de fichiers) car il ne déplace qu'une référence vers le fichier / répertoire. Si je dois effectuer un transfert de données réel, j'utilise rsyncsi l'une des conditions suivantes est vraie: 1) Je déplace plus de fichiers que je ne peux en vérifier le transfert en un coup d'œil; 2) Je prévois avoir besoin de garder les fichiers synchronisés; 3) Je pense que le transfert pourrait être interrompu. Mon point est, pour le cas d'utilisation que vous présentez dans la question, rsyncest tout simplement l'outil, et mvou cpne sont pas.
Silly Freak
7
Je conseillerais de toujours exécuter n'importe quelle commande rsync avec -v et —dry-run d'abord pour confirmer exactement ce qu'elle va faire.
Darren