J'ai deux disques avec les mêmes fichiers, mais la structure du répertoire est totalement différente.
Existe-t-il un moyen de «déplacer» tous les fichiers du côté destination afin qu'ils correspondent à la structure du côté source? Avec un script peut-être?
Par exemple, le lecteur A a:
/foo/bar/123.txt
/foo/bar/234.txt
/foo/bar/dir/567.txt
Alors que le lecteur B a:
/some/other/path/123.txt
/bar/doo2/wow/234.txt
/bar/doo/567.txt
Les fichiers en question sont énormes (800 Go), donc je ne veux pas les recopier; Je veux juste synchroniser la structure en créant les répertoires nécessaires et en déplaçant les fichiers.
Je pensais à un script récursif qui trouverait chaque fichier source sur la destination, puis le déplacerait dans un répertoire correspondant, le créant si nécessaire. Mais - cela dépasse mes capacités!
Une autre solution élégante a été donnée ici: /superuser/237387/any-way-to-sync-directory-structure-when-the-files-are-already-on-both-sides/238086
Réponses:
Je vais avec Gilles et vous montrerai Unison comme suggéré par hasen j . Unison était DropBox 20 ans avant DropBox. Un code solide que beaucoup de gens (moi y compris) utilisent tous les jours - très intéressant à apprendre. Pourtant, il a
join
besoin de toute la publicité qu'il peut obtenir :)Ce n'est qu'une demi-réponse, mais je dois retourner au travail :)
Fondamentalement, je voulais démontrer l'
join
utilitaire peu connu qui fait exactement cela: joint deux tables sur un certain champ.Tout d'abord, configurez un scénario de test comprenant des noms de fichiers avec des espaces:
(modifiez des noms de répertoires et / ou de fichiers dans
new
).Maintenant, nous voulons construire une carte: hachage -> nom de fichier pour chaque répertoire, puis utiliser
join
pour faire correspondre les fichiers avec le même hachage. Pour générer la carte, mettez ce qui suit dansmakemap.sh
:makemap.sh
crache un fichier avec des lignes de la forme, 'hachage "nom de fichier"', donc nous nous joignons juste sur la première colonne:Cela génère
moves.txt
ce qui ressemble à ceci:La prochaine étape serait de faire les mouvements, mais mes tentatives se sont bloquées sur les citations ...
mv -i
etmkdir -p
devraient être utiles.la source
join
est vraiment intéressant. Merci de l'avoir porté à mon attention.join
entrée?Il existe un utilitaire appelé unisson:
http://www.cis.upenn.edu/~bcpierce/unison/
Description du site:
Notez que Unison ne détecte les fichiers déplacés lors de la première exécution que si au moins une des racines est distante, donc même si vous synchronisez des fichiers locaux, utilisez-la
ssh://localhost/path/to/dir
comme l'une des racines.la source
Utilisez Unison comme suggéré par hasen j . Je laisse cette réponse comme un exemple de script potentiellement utile ou pour une utilisation sur un serveur avec uniquement des utilitaires de base installés.
Je suppose que les noms de fichiers sont uniques dans toute la hiérarchie. Je suppose également qu'aucun nom de fichier ne contient de nouvelle ligne et que les arborescences de répertoires ne contiennent que des répertoires et des fichiers normaux.
Collectez d'abord les noms de fichiers côté source.
Ensuite, déplacez les fichiers en place du côté destination. Tout d'abord, créez une arborescence de fichiers aplatie du côté destination. Utilisez
ln
au lieu demv
si vous souhaitez conserver les liens durs dans l'ancienne hiérarchie.Si certains fichiers peuvent être manquants dans la destination, créez un aplatissement similaire
/A.staging
et utilisez rsync pour copier les données de la source vers la destination.Renommez maintenant les fichiers en place.
De manière équivalente:
Enfin, si vous vous souciez des métadonnées des répertoires, appelez rsync avec les fichiers déjà en place.
Notez que je n'ai pas testé les extraits de cet article. À utiliser à vos risques et périls. Veuillez signaler toute erreur dans un commentaire.
la source
En particulier, si la synchronisation en cours est utile, vous pouvez essayer de comprendre git-annex .
C'est relativement nouveau; Je n'ai pas essayé de l'utiliser moi-même.
Je peux le suggérer car il évite de conserver une deuxième copie des fichiers ... cela signifie qu'il doit marquer les fichiers en lecture seule ("verrouillés"), comme certains systèmes de contrôle de version non Git.
Les fichiers sont identifiés par l'extension de fichier sha256sum + (par défaut). Il devrait donc être capable de synchroniser deux dépôts avec un contenu de fichier identique mais des noms de fichiers différents, sans avoir à effectuer d'écritures (et sur un réseau à faible bande passante, si vous le souhaitez). Il faudra bien sûr lire tous les fichiers pour les additionner.
la source
Que diriez-vous quelque chose comme ça:
Cela suppose que les noms des fichiers que vous souhaitez synchroniser sont uniques sur l'ensemble du lecteur: sinon, il ne peut pas être entièrement automatisé (cependant, vous pouvez fournir une invite pour que l'utilisateur choisisse le fichier à choisir s'il y en a plus d'un).
Le script ci-dessus fonctionnera dans des cas simples, mais peut échouer s'il
name
se trouve qu'il contient des symboles qui ont une signification particulière pour les expressions régulières. Lagrep
liste des fichiers sur peut également prendre beaucoup de temps s'il y a beaucoup de fichiers. Vous pouvez envisager de traduire ce code pour utiliser une table de hachage qui mappera les noms de fichiers en chemins, par exemple dans Ruby.la source
grep
ligne? Trouve-t-il simplement le chemin complet du fichier correspondant dansdstlist
?ln
il crée des liens symboliques. Vous pouvez utilisermv
pour déplacer les fichiers, mais attention à remplacer les fichiers existants. En outre, vous souhaiterez peut-être nettoyer les répertoires vides, le cas échéant, après avoir éloigné les fichiers. Oui, cettegrep
commande recherche une ligne qui se termine sur le nom de fichier, révélant ainsi le chemin d'accès complet à celui-ci sur le lecteur de destination.En supposant que les noms de fichiers de base sont uniques dans les arbres, c'est assez simple:
Si vous vouliez nettoyer les anciens répertoires vides, utilisez:
la source
J'ai également rencontré ce problème. La solution basée sur md5sum n'a pas fonctionné pour moi, car je synchronise mes fichiers sur un
webdav
montage. Le calcul des sommes md5sum sur lawebdav
destination signifierait également des opérations de fichiers volumineux.J'ai fait un petit script
reorg_Remote_Dir_detect_moves.sh
(sur github) qui essaie de détecter les fichiers les plus déplacés et crée ensuite un nouveau script shell temporaire avec plusieurs commandes pour ajuster le répertoire distant. Comme je ne m'occupe que des noms de fichiers, le script n'est pas une solution parfaite.Pour des raisons de sécurité, plusieurs fichiers seront ignorés: A) Les fichiers avec le même (même début) noms de chaque côté, et B) Les fichiers qui ne sont que du côté distant. Ils seront ignorés et ignorés.
Les fichiers ignorés seront ensuite traités par votre outil de synchronisation préféré (par exemple,
rsync, unison
, ...), que vous devrez utiliser après avoir exécuté le script shell temporaire.Alors peut-être que mon script est utile pour quelqu'un? Si c'est le cas (pour être plus clair), il y a trois étapes:
reorg_Remote_Dir_detect_moves.sh
(sur github)/dev/shm/REORGRemoteMoveScript.sh
=> exécutez ceci pour faire les mouvements (sera rapide sur montéwebdav
)rsync, unison
, ...)la source
Voici ma tentative de réponse. En guise d'avertissement, toute mon expérience de script vient de bash, donc si vous utilisez un shell différent, les noms de commande ou la syntaxe peuvent être différents.
Cette solution nécessite la création de deux scripts séparés.
Ce premier script est chargé de déplacer réellement les fichiers sur le lecteur de destination.
Le deuxième script crée le fichier de mappage md5 utilisé par le premier script, puis appelle le premier script sur chaque fichier du lecteur de destination.
Fondamentalement, ce qui se passe est que les deux scripts simulent un tableau associatif avec
$md5_map_file
. Tout d'abord, tous les md5 des fichiers sur le lecteur source sont calculés et stockés. Les md5 sont associés aux chemins relatifs depuis la racine du lecteur. Ensuite, pour chaque fichier sur le lecteur de destination, le md5 est calculé. En utilisant ce md5, le chemin de ce fichier sur le lecteur source est recherché. Le fichier sur le lecteur de destination est ensuite déplacé pour correspondre au chemin du fichier sur le lecteur source.Il y a quelques mises en garde avec ce script:
la source
md5sum
ne semble pas être la chose à utiliser ici. (BTW,rsync
a un mode dans lequel il ne calcule pas les sommes de contrôle.)