Comment synchroniser deux dossiers avec des outils de ligne de commande?


64

Ayant migré de Linux vers Windows, j'aimerais trouver un logiciel alternatif à Winmerge ou plutôt apprendre à utiliser des outils de ligne de commande pour comparer et synchroniser deux dossiers sous Linux. Je vous serais reconnaissant de bien vouloir me dire comment effectuer les tâches suivantes en ligne de commande ... (J'ai étudié diff et rsync, mais j'ai toujours besoin d'aide.)

Nous avons deux dossiers: "/ home / user / A" et "/ home / user / B"

Le dossier A est l'endroit où les fichiers et les dossiers normaux sont enregistrés et le dossier B est un dossier de sauvegarde qui sert de miroir complet au dossier A. (Rien n'est directement enregistré ou modifié par l'utilisateur dans le dossier B.)

Mes questions sont:

  • Comment lister les fichiers qui n'existent que dans le dossier B? (Par exemple, ceux supprimés du dossier A depuis la dernière synchronisation.)

  • Comment copier des fichiers existant uniquement dans le dossier B dans le dossier A?

  • Comment répertorier les fichiers qui existent dans les deux dossiers mais dont l’horodatage ou la taille sont différents? (Ceux qui ont été modifiés dans le dossier A depuis la dernière synronisation. J'aimerais éviter d'utiliser des sommes de contrôle, car il existe des dizaines de milliers de fichiers et cela ralentirait le processus.)

  • Comment faire une copie exacte du dossier A dans le dossier B? Je veux dire, tout copier du dossier A dans le dossier B existant uniquement dans le dossier A et supprimer tout le contenu du dossier B existant uniquement dans le dossier B, sans toucher aux fichiers identiques dans les deux dossiers.


Pourquoi ne pas utiliser un programme de sauvegarde approprié pour cela? La duplicité est un exemple.
Qudit

Réponses:


89

Cela met le dossier A dans le dossier B:

rsync -avu --delete "/home/user/A" "/home/user/B"  

Si vous voulez que le contenu des dossiers A et B soit identique, insérez /home/user/A/(avec la barre oblique) comme source. Cela ne prend pas le dossier A mais tout son contenu et le place dans le dossier B. Comme ceci:

rsync -avu --delete "/home/user/A/" "/home/user/B"
  • -a Faire la synchronisation en préservant tous les attributs du système de fichiers
  • -v courir verbalement
  • -u copier uniquement les fichiers avec une heure de modification plus récente (ou une différence de taille si les heures sont égales)
  • --delete supprimer les fichiers du dossier cible qui n'existent pas dans la source

Manpage: https://download.samba.org/pub/rsync/rsync.html


7
rsync : lancez l'application rsync, -a : faites la synchronisation en préservant tous les attributs du système de fichiers, -v : lancez verbalement, -z : compressez les données pendant la synchronisation (transportez les données en mode compressé), --delete : supprimez les fichiers de la cible dossier qui n'existe pas dans le source, / home / utilisateur / A : dossier source, / home / utilisateur / B : dossier cible
SonicARG

Bonjour SonicARG, j'ai totalement oublié de revenir à cela et de mettre l'explication, merci de soumettre l'explication, j'ai mis la vôtre dans la réponse, j'espère que cela ne vous dérange pas
TuxForLife

6
Rsync est principalement conçu pour copier des fichiers entre différents ordinateurs. Comme expliqué ici, il peut également servir à synchroniser des répertoires. L’option -z est donc intéressante pour réduire le trafic réseau et améliorer ainsi les performances d’un rsync entre 2 ordinateurs: (lire les données du disque -> compresser) === réseau ===> (décompresser-> écrire sur le disque) Utilisation de - z synchroniser 2 répertoires sur le même hôte est un peu idiot et une perte de cycle de processeur que vous obtiendrez (lire les données du disque -> compresser -> décompresser -> écrire sur le disque)
GerritCap

@GerritCap, j'ai effectué un montage, merci pour votre précieuse contribution
TuxForLife

1
J'ai essayé la commande mais elle crée un sous-répertoire /home/user/B/Aau lieu de remplacer le contenu de A par le contenu de B. Pourriez-vous m'aider à le regarder?
Luc

11

Vous pourriez unisonutiliser un outil développé par Benjamin Pierce à U Penn.

Supposons que vous avez deux répertoires,

/home/user/Documents/dirA/ et /home/user/Documents/dirB/

Pour synchroniser ces deux éléments, vous pouvez utiliser:

~ $unison -ui text /home/user/Documents/dirA/ /home/user/Documents/dirB/

En sortie, unisonaffichera chaque répertoire et fichier différent des deux répertoires que vous avez demandé de synchroniser. Il recommandera à additivement Synchronize (répliquées fichier manquant dans les deux endroits) sur la course initiale, puis créer et maintenir un arbre de synchronisation sur votre machine, et sur les exécutions ultérieures , il mettra en œuvre la synchronisation vraie ( par exemple, si vous supprimez un fichier .../dirA, il seront supprimés à partir .../dirBainsi. Vous pouvez également comparer chaque changement et éventuellement choisir de transmettre ou inverse synchronisation entre les deux répertoires.

Facultativement, pour lancer l'interface graphique, supprimez simplement l' -ui textoption de votre commande, bien que je trouve le cliplus simple et plus rapide à utiliser.

Plus à ce sujet: tutoriel Unison dans la documentation utilisateur Unison .


1

La réponse de TuxForLife est plutôt bonne, mais je vous suggère fortement de l’utiliser -clors de la synchronisation locale. Vous pouvez faire valoir que cela ne vaut pas la peine de temps / réseau de le faire pour les synchronisations à distance, mais cela en vaut la peine pour les fichiers locaux car la vitesse est si grande.

-c, --checksum
       This forces the sender to checksum every regular file using a 128-bit  MD4
       checksum.   It  does this during the initial file-system scan as it builds
       the list of all available files. The receiver then checksums  its  version
       of  each  file  (if  it exists and it has the same size as its sender-side
       counterpart) in order to decide which files need to be updated: files with
       either  a  changed  size  or a changed checksum are selected for transfer.
       Since this whole-file checksumming of all files on both sides of the  con-
       nection  occurs  in  addition to the automatic checksum verifications that
       occur during a file's transfer, this option can be quite slow.

       Note that rsync always verifies that each transferred file  was  correctly
       reconstructed  on  the receiving side by checking its whole-file checksum,
       but that automatic after-the-transfer verification has nothing to do  with
       this  option's  before-the-transfer  "Does  this file need to be updated?"
       check.

Cela montre à quel point le fait d’avoir la même taille et la même heure peut vous manquer.

La mise en place

$ cd /tmp

$ mkdir -p {A,b}/1/2/{3,4}

$ echo "\___________from A" | \
      tee A/1/2/x  | tee A/1/2/3/y  | tee A/1/2/4/z  | \
  tr A b | \
      tee b/1/2/x  | tee b/1/2/3/y  | tee b/1/2/4/z  | \
      tee b/1/2/x0 | tee b/1/2/3/y0 >     b/1/2/4/z0

$ find A b -type f | xargs -I% sh -c "echo %; cat %;"
A/1/2/3/y
\___________from A
A/1/2/4/z
\___________from A
A/1/2/x
\___________from A
b/1/2/3/y
\___________from b
b/1/2/3/y0
\___________from b
b/1/2/4/z
\___________from b
b/1/2/4/z0
\___________from b
b/1/2/x
\___________from b
b/1/2/x0
\___________from b

Le rsync qui ne copie rien car les fichiers ont tous la même taille et le même horodatage

$ rsync -avu A/ b
building file list ... done

sent 138 bytes  received 20 bytes  316.00 bytes/sec
total size is 57  speedup is 0.36

$ find A b -type f | xargs -I% sh -c "echo %; cat %;"
A/1/2/3/y
\___________from A
A/1/2/4/z
\___________from A
A/1/2/x
\___________from A
b/1/2/3/y
\___________from b
b/1/2/3/y0
\___________from b
b/1/2/4/z
\___________from b
b/1/2/4/z0
\___________from b
b/1/2/x
\___________from b
b/1/2/x0
\___________from b    

Le rsync qui fonctionne correctement car il compare les sommes de contrôle

$ rsync -cavu A/ b
building file list ... done
1/2/x
1/2/3/y
1/2/4/z

sent 381 bytes  received 86 bytes  934.00 bytes/sec
total size is 57  speedup is 0.12

$ find A b -type f | xargs -I% sh -c "echo %; cat %;"
A/1/2/3/y
\___________from A
A/1/2/4/z
\___________from A
A/1/2/x
\___________from A
b/1/2/3/y
\___________from A
b/1/2/3/y0
\___________from b
b/1/2/4/z
\___________from A
b/1/2/4/z0
\___________from b
b/1/2/x
\___________from A
b/1/2/x0
\___________from b

Est-ce que -c et -u fonctionnent bien ensemble?
Sergey Korzhov

@SergeyKorzhov c'est le cas. Le `-u 'fonctionne toujours comme d'habitude pour mettre à jour que si la destination n'est pas plus récente.
Bruno Bronosky le

1

C’est ce que j’utilise pour la sauvegarde de fichiers personnels. Je ne me soucie pas de tout ce qui est couvert -aet je veux imprimer plus d’informations utiles.

rsync -rtu --delete --info=del,name,stats2 "/home/<user>/<src>/" "/run/media/<user>/<drive>/<dst>"

À partir de la page de manuel rsync :

-r, --recursive
Ceci indique à rsync de copier les répertoires de manière récursive.

-t, --times
Ceci indique à rsync de transférer les heures de modification avec les fichiers et de les mettre à jour sur le système distant.

-u, --update
Ceci oblige rsync à ignorer tous les fichiers présents dans la destination et dont l'heure de modification est plus récente que celle du fichier source. (Si un fichier de destination existant a une heure de modification égale à celle du fichier source, il sera mis à jour si les tailles sont différentes.)

--delete
Ceci indique à rsync de supprimer les fichiers superflus du côté de réception (ceux qui ne sont pas du côté de l'envoi), mais uniquement pour les répertoires en cours de synchronisation.

--info = FLAGS
Cette option vous permet d’avoir un contrôle précis de la sortie des informations que vous souhaitez voir.

De rsync --info=help

DEL        Mention deletions on the receiving side  
NAME       Mention 1) updated file/dir names, 2) unchanged names  
STATS      Mention statistics at end of run (levels 1-3)

Bien que moins explicite, ceci est apparemment équivalent et plus court:

rsync -rtuv --delete --info=stats2 "/home/<user>/<src>/" "/run/media/<user>/<drive>/<dst>"

-v, --verbose
Un simple -v vous donnera des informations sur les fichiers en cours de transfert et un bref résumé à la fin [stats1].


0

Ce n'est pas tout à fait la même chose que ce que vous demandez, mais vous pouvez envisager d'utiliser un outil de contrôle de version. Des outils comme Git font tout ce que vous demandez, et plus encore, en particulier si vous ne travaillez pas directement dans le dossier B, il peut être intéressant de le consulter. vous pouvez trouver plus d'informations sur git ici


2
Cela ne fonctionne que si vous êtes prêt à tout ajouter au contrôle de version. Cela oblige également tous les changements jamais engagés à être stockés de manière permanente, ce qui peut être indésirable.
Qudit

@ Qudit, c'est vrai, bien qu'il soit possible via le clonage de limiter l'historique, mais limiter l'historique n'est pas (encore?) Implémenté dans Git par défaut.
switch87

@ switch87 Oui, je sais que vous pouvez supprimer les anciens commits. Le contrôle de version n'est pas vraiment une solution appropriée pour les sauvegardes génériques, surtout s'il y a de gros fichiers binaires.
Qudit

Sa question concerne la sauvegarde locale, mais si vous l'utilisez pour la sauvegarde à distance, vous pouvez toujours utiliser git annex pour les fichiers plus volumineux. pour la sauvegarde locale, ce n'est pas un problème.
switch87

2
@ switch87 Cela aurait vraiment dû être un commentaire sur le Q et non une réponse, car cela n'explique pas comment vous utiliseriez git pour faire des sauvegardes.
slm

0

Vous pouvez l'utiliser de cette façon:

rsync -avu --delete /home/user/A/* /home/user/B/

De cette façon, vous allez copier le contenu du dossier A dans le dossier B, pas le contenu du dossier A lui-même.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.