Comment comparez-vous deux dossiers et copiez la différence dans un troisième dossier?


23

Vous avez trois dossiers:

  • dossier actuel , qui contient vos fichiers actuels
  • dossier ancien , qui contient une ancienne version des mêmes fichiers
  • différence de dossier , qui est juste un dossier vide

Comment comparez-vous l' ancien avec l' actuel et copiez les fichiers qui sont différents (ou entièrement nouveaux) dans le courant à la différence ?


J'ai cherché tout autour et cela semble être une chose simple à aborder, mais je ne peux pas le faire fonctionner dans mon exemple particulier. La plupart des sources ont suggéré l'utilisation de rsync , je me suis donc retrouvé avec la commande suivante:

rsync -ac --compare-dest=../old/ new/ difference/

Cependant, cela copie tous les fichiers du nouveau vers la différence , même ceux qui sont les mêmes que dans l' ancien .

Au cas où cela aiderait (peut-être que la commande est correcte et que la faute est ailleurs), voici comment j'ai testé ceci:

  1. J'ai fait les trois dossiers.
  2. J'ai fait plusieurs fichiers texte avec des contenus différents en ancien .
  3. J'ai copié les fichiers de l' ancien vers le nouveau .
  4. J'ai changé le contenu de certains fichiers dans de nouveaux fichiers et ajouté quelques fichiers supplémentaires.
  5. J'ai exécuté la commande ci-dessus et vérifié les résultats dans la différence .

Je cherchais une solution depuis quelques jours et j'apprécierais vraiment de l'aide. Il ne doit pas nécessairement utiliser rsync, mais j'aimerais savoir si je me trompe si possible.



@wingedsubmariner Je ne pense pas que ce soit un doublon, car la réponse acceptée à la question liée est la commande sur laquelle l'OP pose une question.
Bernhard

@Bernhard Ah, mon mauvais. Je suppose que j'ai mal compris la question initiale.
wingedsubmariner

@wingedsubmariner Pas de soucis, vous avez dit "possible", et je suis d'accord que ça ressemble beaucoup :)
Bernhard

Réponses:


7

Je ne sais pas si vous pouvez le faire avec des commandes Linux existantes telles que rsync ou diff. Mais dans mon cas, j'ai dû écrire mon propre script en utilisant Python, car python a le module "filecmp" pour la comparaison de fichiers. J'ai posté l'intégralité du script et de son utilisation sur mon site personnel - http://linuxfreelancer.com/

Son utilisation est simple - donnez-lui le chemin absolu du nouveau répertoire, de l'ancien répertoire et du répertoire de différence dans cet ordre.

#!/usr/bin/env python

import os, sys
import filecmp
import re
from distutils import dir_util
import shutil
holderlist=[]

def compareme(dir1, dir2):
    dircomp=filecmp.dircmp(dir1,dir2)
    only_in_one=dircomp.left_only
    diff_in_one=dircomp.diff_files
    dirpath=os.path.abspath(dir1)
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in only_in_one]
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in diff_in_one]
    if len(dircomp.common_dirs) > 0:
        for item in dircomp.common_dirs:
            compareme(os.path.abspath(os.path.join(dir1,item)), os.path.abspath(os.path.join(dir2,item)))
        return holderlist

def main():
 if len(sys.argv) > 3:
   dir1=sys.argv[1]
   dir2=sys.argv[2]
   dir3=sys.argv[3]
 else:
   print "Usage: ", sys.argv[0], "currentdir olddir difference"
   sys.exit(1)

 if not dir3.endswith('/'): dir3=dir3+'/'

 source_files=compareme(dir1,dir2)
 dir1=os.path.abspath(dir1)
 dir3=os.path.abspath(dir3)
 destination_files=[]
 new_dirs_create=[]
 for item in source_files:
   destination_files.append(re.sub(dir1, dir3, item) )
 for item in destination_files:
  new_dirs_create.append(os.path.split(item)[0])
 for mydir in set(new_dirs_create):
   if not os.path.exists(mydir): os.makedirs(mydir)
#copy pair
 copy_pair=zip(source_files,destination_files)
 for item in copy_pair:
   if os.path.isfile(item[0]):
    shutil.copyfile(item[0], item[1])

if __name__ == '__main__':
 main()

21

J'ai compris quel était le problème dans mon cas:

Les fichiers que je comparais avaient des horodatages différents. Je n'aurais pas dû utiliser l' argument -a , je suppose que rsync essayait de conserver les horodatages lors de la copie des fichiers. La commande qui a fonctionné pour moi était:

rsync -rvcm --compare-dest=../old/ new/ difference/

Je pense que pour tester cela avec l'option -a (archive), vous devriez avoir utilisé rsync -apour "copier" les fichiers initialement (ou l'équivalent cp), puis supprimés ou modifiés. (J'aime m'en tenir à rsync parce que je sais qu'il est cohérent sans penser à ce qu'il pourrait faire.) Je pense que cela aurait dû fonctionner avec la commande d'origine. L'option -a inclut -t (comparer par horodatage), qui est l'alternative à -c (comparer par somme de contrôle).
sauge

2
À mon avis, cette réponse devrait être celle qui est acceptée, car elle est beaucoup plus simple. De plus, la commande n'a fonctionné pour moi que lorsque j'ai fourni le chemin complet pour old/et new/.
Yamaneko

La mise en garde semble être que le compar-dest doit être le chemin relatif vers la différence vu de l'intérieur du dest réel
Ryan Williams

1

Cela pourrait aider certains lecteurs: sous Windows, un petit programme gratuit plus ancien - Third Dir - fait exactement ce qui est demandé ici. Il n'est plus disponible via le développeur, Robert Vašíček. Mais je suis sûr qu'il peut être trouvé via certains référentiels en ligne.

Voici la description du développeur, qui reste sur son site:

Troisième Dir: Un synchroniseur de répertoire inhabituel - les différents fichiers sont copiés dans le troisième répertoire. Il est très utile d'extraire, par exemple, des photos nouvelles ou modifiées d'une immense arborescence de répertoires sur un disque fixe vers un dossier temporaire, puis de les ajouter au CD d'archivage (remarque - les fichiers originaux sont comparés au CD). Version 1.4, taille 23kB. Créé le 2005-02-12.

Historique: Version 1.14 - Plus efficace lorsque plusieurs dizaines de milliers de fichiers sont comparés.


0

La manière rsync donnée par Thane avec les ajouts de Yamaneko fonctionne très bien mais laisse des répertoires vides. Pour moi, la solution finale était en deux étapes, appelez d'abord rsync avec le chemin complet, puis une commande find pour supprimer tous les répertoires vides:

rsync -rvcm --compare-dest=/tmp/org/ /tmp/new/ /tmp/difference/
find /tmp/difference/ -d -type d -empty -exec rmdir {} \; -print

Veuillez noter que même avec l'option --links, rsync n'a pas conservé les liens symboliques mais a copié les données de destination à la place.


Notez qu'au lieu de -empty -exec rmdir {} \;vous pouvez utiliser -empty -delete.
mivk

-3

J'utilise l'explorateur XY dualpane (commercial), qui peut faire beaucoup de tours et c'est l'un d'entre eux. Ouvrez Currentdans un volet et ancien dans l'autre. Activez le volet Actuel. Allez dans Volets > Sync Select. Il vous donne 5 options pour sélectionner:

  1. Matchs (répertoriés dans les deux)
  2. Uniques (dans le volet actif)
  3. Plus récent (dans le volet actif)
  4. Fichiers uniques et plus récents (dans le volet actif)
  5. Sélectionné (ceux sélectionnés dans l'autre volet)

Vous pouvez maintenant copier la sélection résultante de l' Currentendroit où vous le souhaitez. Je l'ai utilisé pour comparer mailfoldersd'anciennes installations avec les dernières. La structure des dossiers était assez complexe, mais (presque) tous mbs-filesavaient un numéro unique.

J'ai donc fait une recherche sur mbs-filesl'ancienne racine mailfolder(dans un volet) ainsi que sur la plus récente (dans l'autre volet) et j'ai fait une comparaison sur les résultats de la recherche dans chaque volet ( Sync Select Unique , pour trouver les courriers manquants pendant réinstalle)! Vous pouvez également définir de nombreuses options.


1
Si vous parlez de logiciels non standard, vous devez inclure un lien. Si vous voulez dire XYplorer, cela ne va pas du tout aider le PO.
Anthon
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.