Travaillant sur un vieux projet PHP, j’ai été confronté à de vieux fichiers cradingues encodés en UTF-8 AVEC BOM, posant des problèmes d’affichages et de redirections.
Le BOM, si vous ne savez pas ce que c’est, c’est un caractère se situant généralement en début de fichier servant à déterminer en quel type d’UTF est encodé un fichier (UTF-8, 16, 32, autres ?). Ce marqueur n’étant pas nécessaire en UTF-8, il nous pose plus de problèmes qu’autre chose et l’on a pour habitude de l’omettre.
Après quelques recherches, je suis tombé sur des bouts de scripts sur le forum d’Ubuntu, mais ils modifient tous les fichiers présents. J’ai des fichiers encodés en latin9 parmi ceux à corriger, mon but n’est pas de les changer :-/
Du coup, je me suis créé un script bash qui cherche et corrige seulement les fichiers présentant cette particularité, le voici :
#!/bin/bash FROM=UTF-8 TO=UTF-8 ICONV="iconv -f $FROM -t $TO" BASEDIR=${1:-.} # Convert grep -rl $'xEFxBBxBF' "$BASEDIR" | while read fn; do $ICONV "$fn" > "$fn".bak awk '{if(NR==1)sub(/^xefxbbxbf/,"");print}' "$fn".bak > "$fn" rm "$fn".bak echo "$fn" done
Un petit chmod +x sur ce script, vous l’exécutez en passant en paramètre le dossier contenant les fichiers à fixer et c’est fini 😀
Pour les curieux, voici quelques détails supplémentaires sur ce que font les différentes commandes du script :
- ` BASEDIR=${1:-.} ` Cette forme d’assignation de bash permet de définir une valeur par défaut. Si vous ne passez pas de paramètres au script, il prendra le dossier courant (.)
- ` grep -rl $’xEFxBBxBF’ « $BASEDIR » ` Je cherche le marqueur UTF-8 (qui correspond aux caractères Unicode EF, BB puis BF) dans les fichiers (-l) récursivement (-r) et j’envoie ça dans ma grosse boucle ( ͡° ͜ʖ ͡°)
- ` iconv -f $FROM -t $TO « $fn » > « $fn ».bak ` Théoriquement, cette commande ne sert à rien, c’est juste pour s’assurer que le fichier est bien en UTF-8 et que le marqueur UTF est bien au début du fichier.
- ` awk ‘{if(NR==1)sub(/^xefxbbxbf/, » »);print}’ « $fn ».bak > « $fn » ` C’est là que la magie opère, awk supprimant le marqueur diabolique. Notez qu’on aurait surement pu faire pareil avec un sed. C’est cette commande que je cherchais au départ, mais quitte à aller au bout des choses, autant en faire un script complet :3
Et voilà , un problÚme d’encodage en moins !