compare 2 répertoires et copie les différences dans un 3ème répertoire


32

Sous Ubuntu 12.04, je souhaite comparer 2 répertoires, par exemple folder1 / et folder2 / et copier tous les fichiers différents de folder3 /. Il existe également des fichiers imbriqués, les sous-répertoires correspondants doivent donc également être copiés.

Y at-il une seule commande qui pourrait m'aider? Je peux obtenir la liste complète des fichiers modifiés en cours d'exécution:

rsync -rcnC --out-format="%f" folder1/ folder2/

Mais rsync ne semble pas avoir la capacité d'exporter ces fichiers dans un répertoire cible différent. Puis-je diriger la liste vers cp ou un autre programme, afin que les fichiers soient copiés, alors que les répertoires sont également créés? Par exemple, j'ai essayé

rsync -rcnC --out-format="%f" folder1/ folder2/ | xargs cp -t folder3/

mais cela ne conserverait pas non plus les répertoires, il copierait simplement tous les fichiers dans folder3 /


Je voudrais probablement utiliser une combinaison de diff -qret awkpour construire la liste, alors rsync...
ewwhite

Comment pourrais-je utiliser rsync avec la liste?
periklis

Je voudrais soit exécuter une boucle ou utiliser l' rsync --include-from=FILEoption.
ewwhite

(Ne soyez pas paresseux ...) Mais la solution rsync ci-dessous est élégante.
ewwhite

Réponses:


38

Utilisez --compare-dest.

De la page de manuel:

--compare-dest = DIR - Cette option indique à rsync d'utiliser DIR sur la machine de destination en tant que hiérarchie supplémentaire pour comparer les fichiers de destination aux transferts (si ces fichiers sont manquants dans le répertoire de destination). Si un fichier DIR identique au fichier de l'expéditeur est trouvé, le fichier ne sera PAS transféré dans le répertoire de destination. Ceci est utile pour créer une sauvegarde fragmentée de seulement les fichiers qui ont été modifiés depuis une sauvegarde précédente.

vérifiez d'abord votre syntaxe avec --dry-run

rsync -aHxv --progress --dry-run --compare-dest=folder2/ folder1/ folder3/

Ensuite, une fois que vous êtes satisfait du résultat:

rsync -aHxv --progress  --compare-dest=folder2/ folder1/ folder3/

Ce lien explique bien la portée de --compare-dest.


1
Merci pour cela, je n’avais pas compris l’explication de la page de manuel relative à ce paramètre. Pour ceux que ça intéresse, je l'ai fait avecrsync -rcC --compare-dest=folder2/ folder1/ folder3/
periklis

note rapide pour les utilisateurs d’OsX. J'ai rsync version 3.1.1 protocol version 31sur mon local et rsync ne comprend pas les ~/chemins pour --compare-destparam.
Jevgeni Smirnov

4
Pour moi, --compare-destrequis un chemin absolu.
palswim

Cela n'a pas fonctionné pour moi avec les options de l'auteur ou de l'OP. Dire qu'il sorties fonts/Makefile.infichier, ce qui est identique dans les deux folder2et folder1dirs.
Bonjour Angel

3

Ce petit script devrait fonctionner:

folder1="firsts_folder/"
folder2="second_folder/"
folder3="target_folder"
for x in `rsync -rcnC --out-format="%n"  $folder1 $folder2`
    do
        if [ -d "$folder1/$x" ]; then
            mkdir -p "$folder3/$x"
        else
            cp -frv $folder1/$x $folder3/$x
        fi
done

Mais je pense aussi que l’analyse de la sortie de diff -qr serait une meilleure solution car elle vous donne le chemin et le nom de chaque fichier de manière cohérente.

MODIFIER

Ce serait une commande, votre commande légèrement modifiée. Mais cela créera folder1sous le folder3. Et cela ne fonctionne pas avec les chemins complets, mais le script ci-dessus ne fonctionne pas non plus avec les chemins complets.

rsync -rcnC --out-format="\"%f\"" folder1/ folder2/ | xargs cp --parents -rfvt folder3/

Je \"en rsyncpour le faire fonctionner avec des fichiers et des répertoires contenant des blancs. Testé sur Ubuntu 10.04. J'espère que ça aide.


merci pour cela, j'avais espéré qu'un seul commandement existerait bien
periklis

2
rsync -rcnC --out-format="%f" . ../folder2/ |xargs cp --parents -rt ../folder3/

C'est la forme la plus simple que je pourrais trouver, si vous êtes prêt à descendre folder1avant d'envoyer la commande.

C'est l' option la plus lente , mais je pense qu'elle répond à vos exigences et qu'elle peut être exécutée à l'aide de noms de répertoires non relatifs:

rsync -rcnC --out-format="%n" folder1/ folder2/ |grep -vP "/$" |xargs -I{} rsync -R folder1/./{} folder3/

J'ai laissé votre rsynccommande originale seule, parce que vous avez dit qu'elle vous donnait la liste de fichiers correcte (et que mes fichiers de test sont évidemment différents des vôtres, je ne peux donc pas dire avec certitude que j'obtiendrais la liste de fichiers correcte si je déconnais. avec ça).

Le grepest là pour supprimer les noms de répertoire de la sortie de rsync.

La sortie de grepest ensuite transmise à un autre à l' rsyncaide de xargs. Dans param, folder1/./{}extra ./est utilisé pour indiquer à rsync de créer les répertoires relatifs en commençant par ./{}ignorer folder1/. En d'autres termes, cela évite de créer folder3/folder1/.

Je n'ai pu tester cela que sur CentOS 6.4, mais autant que je sache, cela devrait fonctionner de la même manière dans Ubuntu 12.04.

EDIT: Je dois noter que la réponse de smithian est sans aucun doute meilleure, mais je voulais essayer de le faire avec votre rsynccommande originale, car elle vous donnait le résultat souhaité.

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.