Comment copier-fusionner deux répertoires?

113

J'ai deux répertoires images et images2 avec cette structure sous Linux:

/images/ad  
/images/fe  
/images/foo  

... et autres 4000 dossiers

et l'autre est comme:

/images2/ad  
/images2/fe  
/images2/foo

... et autres 4000 dossiers

Chacun de ces dossiers contient des images et les noms des répertoires sous images et images2 sont exactement les mêmes, mais leur contenu est différent. Ensuite, je veux savoir comment je peux copier-fusionner les images de / images2 / ad dans des images / ad, les images de / images2 / foo dans des images / foo et ainsi de suite avec les 4000 dossiers.

ssierral
la source
1
les fichiers de fin sont-ils nommés de la même manière dans les deux répertoires?
Simply_Me
Non ... par exemple dans images / ad sont 1.jpg, 2.jpg et 3.jpg. Mais dans images2 / ad sont 4.jpg et 5.jpg
samedi
4
@AmirAliAkbari, je ne pense pas qu'il s'agisse d'un doublon. L'autre question est essentiellement la suivante: «Est-ce que mv ne fusionne? (réponse: non). Cette question concerne la fusion de 2 hiérarchies de répertoires.
maxschlepzig

Réponses:

174

C'est un travail pour rsync . Cela ne sert à rien de le faire manuellement avec une boucle du shell, sauf si vous souhaitez déplacer le fichier plutôt que de le copier.

rsync -a /path/to/source/ /path/to/destination

Dans ton cas:

rsync -a /images2/ /images/

(Notez la fin de la barre oblique images2, sinon la copie serait copiée /images/images2.)

Si des images portant le même nom existent dans les deux répertoires, la commande ci-dessus sera écrasée /images/SOMEPATH/SOMEFILEpar /images2/SOMEPATH/SOMEFILE. Si vous souhaitez remplacer uniquement les fichiers plus anciens, ajoutez l'option -u. Si vous souhaitez toujours conserver la version /images, ajoutez l'option --ignore-existing.

Si vous souhaitez déplacer les fichiers à partir de /images2, avec rsync, vous pouvez passer l’option --remove-source-files. Ensuite, rsync copie tous les fichiers à tour de rôle et supprime chaque fichier à la fin. Cela est beaucoup plus lent que le déplacement si les répertoires source et de destination se trouvent sur le même système de fichiers.

Gilles
la source
14
..add -P si vous voulez voir des progrès ..
Meetai.com
1
Je voudrais ajouter qu'il n'y a aucun avantage à utiliser une boucle shell délicate ici , même si vous ne voulez les déplacer au lieu de les copier dans ce cas il suffit d' utiliser rsync, alors rm -r /images.
Wildcard
1
J'aimerais également souligner qu'il est important d'inclure les barres obliques de fin pour chaque répertoire . Par exemple, si vous rsync -a images images2exécutez simplement , il ne fera que copier images2 en images au lieu de les fusionner.
Kyle Challis
1
@ s3cur3 Oh. De 2 à (implicite) 1. Ce n'est pas intuitif. Merci, j'ai corrigé ma réponse.
Gilles
1
@ MaxCoplan Non. Rsync n'est pas un outil interactif.
Gilles le
43

Le meilleur choix, comme déjà signalé, est bien sûr rsync. Néanmoins, l'unisson serait également un excellent logiciel pour faire ce travail. Les deux peuvent être utilisés dans plusieurs systèmes d'exploitation.

Rsync

rsync se synchronise dans une direction de la source à la destination. Par conséquent, la déclaration suivante

rsync -avh --progress Source Destination

synchronise tout de la source à la destination . Le dossier fusionné réside dans la destination .

-a signifie "archive" et copie tout de manière récursive de la source à la destination en préservant presque tout.

-v donne plus de sortie ("verbose").

-h pour lisible par l'homme.

--progress pour montrer combien de travail est fait.

Si vous souhaitez uniquement mettre à jour le dossier de destination avec les fichiers les plus récents du dossier source:

rsync -avhu --progress source destination

Unisson

l'unisson se synchronise dans les deux sens. Par conséquent, la déclaration suivante

unison Source Destination

synchronise les deux répertoires dans les deux sens et finalement source est égal à destination. C'est comme faire deux fois rsync d'une source à l'autre et vice versa.

Pour des utilisations plus avancées, consultez les pages de manuel ou les sites Web suivants:

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/
écorcer
la source
2
Je tiens à mentionner que le chemin correct du dossier doit être suivi de la barre oblique finale rsync -avh --progress source/ destination/, sinon le dossier source sera créé dans le dossier de destination, du moins dans mon cas, c'était comme ça.
Electro
Cela fonctionne très bien pour moi (avec la barre oblique dans les dossiers). Je vous remercie!
Leopoldo Sanczyk
5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

Boucle sur tout le contenu de l' images2utilisation d'un glob développé (pour éviter les problèmes d'analyse ls), puis mvle contenu de ces éléments à l'entrée correspondante dans images. Utilise basenamepour éliminer images2le fil conducteur du chemin global.

Etan Reisner
la source
veuillez ajouter plus de détails sur ce que votre commande fait pour qu’elle soit également utile aux futurs lecteurs :)
Ramesh
1

@ inulinux12, vous pouvez utiliser la forboucle d' une ligne suivante depuis la ligne de commande:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

Cela déplacera tous les fichiers images2à imagesleurs répertoires respectifs. Remarque: cela suppose qu'aucun fichier ne porte le même nom.

Par exemple:

Avant exécution:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

Après exécution:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5
Simplement moi
la source
3
Ne pas analyser la sortie de ls. mywiki.wooledge.org/ParsingLs
Etan Reisner
@EtanReisner Merci pour cette suggestion. Les scénarios semblent assez étroits bien que l’information donnée dans la question.
Simply_Me
2
@Simply_Me Même s'il est vrai que ça ira normalement, vous ne voulez vraiment pas que ça explose lorsque vous frappez une affaire sur laquelle vous ne comptiez pas. Cela peut causer de très gros problèmes. Sans parler du fait qu’il est assez souvent (comme dans ce cas-ci) presque trivialement remplaçable par un simple glob. Voir ma réponse comme un exemple de cela.
Etan Reisner
@Simply_Me Les scénarios incluent des noms de fichiers avec des espaces, ce qui est assez commun pour les images.
Gilles
@Gilles et @Etan Reisner, merci pour votre contribution, je l'apprécie! Mis à jour et testé ma réponse pour utiliser la substitution de chaîne, et il est devenu plus rapide que d'utiliser basenamedans cette situation particulière (nul besoin d'appeler basenamepour cela). Merci encore pour vos commentaires constructifs.
Simply_Me