Supprimer récursivement tous les BOM de vos fichiers UTF-8 en un script

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 !

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.