Le premier problème était lié à l'utilisation de l'UTF-8 sous Mac OS, codage que je fais tout pour éviter sur mon Linux depuis des années car en dehors de problèmes d'affichages ça ne m'apporte rien du tout. Mais étant donné la situation j'ai changé le codage des mes noms de fichiers sous Linux en faveur de l'UTF-8 (oui je suis faible).
Une fois ce premier problème réglé, lancement de la synchro avec Unison, une grosse heure pour synchroniser 40Go. Méfiant, je relance la synchro pour m'assurer que tout est bon, et là petite surprise tous les fichiers accentués sont vu comme nouveau sur le Mac et absent sur le Linux. Bon, pourquoi pas, je le laisse relancer la synchro sur ces fichiers. Après cette nouvelle synchro je vais voir mon arborescence sous Linux pour vérifier ce que vient de faire Unison et petite surprise tout mes fichiers accentués apparaissent en double.
S'en suit alors une journée entière de mise à jour d'Unison, de nouvelles synchros, de parcours de forums sans réels résultats. Je me suis donc posé la question calmement : comment Unison a-t-il réussit à créer des fichiers avec le même nom ? c'est impossible, personne ne l'aurait laissé faire. C'est alors que j'ai commencé à porter mes soupçons sur mon vieil ennemi l'UTF-8, après tout il y a peut-être des versions dérivées avec des codages différent dont une sur Mac OS, ce qui pourrait expliquer la situation.
Je me suis donc mit en quête d'informations sur cette mystérieuse implémentation de l'UTF-8 sur Mac OS pour finalement apprendre que l'UTF-8 permet de coder certains caractères de plusieurs manières, notamment les caractères accentués. Par exemple le "é" peut s'écrire avec un seul caractère unicode (U+00E9, LATIN SMALL LETTER E WITH ACUTE), ou en combinant le e avec l'accent (U+0065, LATIN SMALL LETTER E and U+0301, COMBINING ACUTE ACCENT), magique n'est-ce pas ? En résumé Mac OS utilise bien l'UTF-8 mais dans sa forme "décomposée" (parfois appelée UTF-8-MAC), alors que Windows et Linux préfèrent la forme "précomposée", c'est beau les formats universels non ?
Donc comment réussir à synchroniser ces deux arborescences qui contiennent la même chose (ou presque). Et bien je vous livre les 2 solutions trouvées sur les forums puis ma solution à moi :
Solution basique
Ne pas utiliser de caractères accentués, n'utiliser que des caractères ASCII. Pourquoi pas mais ça serait comme baisser son pantalon devant l'UTF-8.
Solution SSHFS
Monter l'arborescence Linux sur le Mac via sshfs en ajoutant l'option "-o modules=iconv,from_code=UTF-8,to_code=UTF-8-MAC", ainsi j'ai accès sur le Mac à l'arborescence Linux convertie à l'unicode Ensuite il suffit de synchroniser les deux arborescences locales sur le Mac.
Cette solution est fonctionnelle, mais d'une part la synchro est très longue à se faire car tout est vérifié sur la même machine et d'autre part il est nécessaire d'avoir les même uid/gid entre Linux et Mac pour la synchro.
Solution "mais si ça doit marcher"
Modifier le codage des fichiers sur Linux le temps de faire la synchro et restaurer l'ancien codage après la synchro.
Un peu "olé olé" me direz vous, mais voyons comment mettre ça en oeuvre. Seul point dur, le renommage des fichiers, il existe des outils tel que convmv qui renommer une arborescence en changeant le codage, mais le format UTF-8-MAC est complètement inconnue par tout ces outils sous Linux. Je me suis donc lancé dans l'écriture d'un script python pour effectuer ces modifications (voir le code en fin de billet). Ensuite la synchronisation est toute simple, modification du codage, appel à Unison, et restauration du codage et en plus ça marche et c'est rapide ! Pfiou !
Pour conclure je dis vive l'UTF-8, le format universel qui j'en suis sur continuera de poser universellement des problèmes durant de longues années.
Et pour re-conclure, voici le "fameux" script python pour changer le codage d'une arborescence (évidemment c'est copyleft) :
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from optparse import OptionParser
from unicodedata import normalize
import os
import os.path
import sys
# ----------------------------------------------------------------------
def composedToDecomposed( string ):
decomposed = normalize( "NFD", string )
return decomposed
def decomposedToComposed( string ):
composed = normalize( "NFC", string )
return composed
# ----------------------------------------------------------------------
def processTree( path, convert ):
for file in os.listdir( path ):
fileWithPath = os.path.join(path,file)
if os.path.isdir( fileWithPath ):
processTree( fileWithPath, convert )
converted = convert(file)
if converted != file:
os.rename(fileWithPath,os.path.join(path,converted))
parser = OptionParser()
parser.add_option( "-d", "--composed-to-decomposed", dest="c2d"
, action="store_true", default=False
, help="convert tree from composed to decomposed form")
parser.add_option( "-c", "--decomposed-to-composed", dest="d2c"
, action="store_true", default=False
, help="convert tree from decomposed to composed form")
(options, args) = parser.parse_args()
if options.c2d == False and options.d2c == False:
print "- E - You must specifiy a conversion"
parser.print_help()
exit(1)
if options.c2d == True and options.d2c == True:
print "- E - Only one conversion can be processed at a time"
parser.print_help()
exit(1)
if options.c2d == True:
label ="from composed form to decomposed"
action = composedToDecomposed
else:
label ="from decomposed form to composed"
action = decomposedToComposed
for tree in args:
print "- I - Converting %s %s" % (tree,label)
tree = unicode(tree, sys.stdin.encoding)
processTree( os.path.abspath(tree), action )
PS: j'ai été faignant, le script ne renomme pas le dossier père de l'arborescence à modifier.