Il y a encore quelques années, j’étais un petit con qui écrivait ses codes en ISO… Cela me suffisait. Mais voilà! Entre temps, j’ai été contaminé par le virus UTF-8. Alors du coup, quand il m’arrive de reprendre de très vieux fichiers, il faut que je les convertisse en UTF-8. Et quand il y a tout un répertoire, autant dire que je n’ai pas du tout envie de m’y coller manuellement.
Conversion de l’encodage d’un fichier: première approche
Je suis tombé un jour sur un code, sans doute trop vieux, qui est à mes yeux assez long… et qui ne fonctionne pas chez moi:
def typecode(dossier,fichier): # détermine l'encodage du fichier d = os.path.join(dossier, fichier) fich = open(d,'rb') contenu=fich.read() fich.close() codage=chardet.detect(contenu)['encoding'] return codage def conversion(dossier,fichier): # conversion en utf-8 fichiertemp="utf-"+fichier conv = "iconv -f " + 'latin1' + " -t utf-8 "+ fichier + " > " + fichiertemp os.system(conv) def suppression(dossier,fichier): ## je sais que c'est étrange mais sinon, le changement ## de nom fait apparaître des caractères non conformes source="utf-"+fichier destination=fichier temporaire = "temp-"+fichier os.rename(source,temporaire) retour = source + " renommé en " + destination os.remove(fichier) os.rename(temporaire,destination) print(retour) def convertir(dossier,fichier): # conversion des fichiers chemin = os.path.join(dossier, fichier) if os.path.splitext(chemin)[1] in liste_ext: code = typecode(dossier,fichier) if code =='windows-1251' or code == 'ISO-8859-2' \ or code == 'ISO-8859-2' or code == 'latin1' \ or code == 'windows-1255': conversion(dossier,fichier) retour = fichier + ' converti de ' + code + ' en utf-8' elif code == 'utf-8' or code == 'UTF-8': retour = fichier + ' déjà au format ' + code else: try: retour = fichier + ' au format ' + code except: retour=None pass print(retour) curdir='.' # remplacer ici par le chemin for dossier, sous_dossiers, fichiers in os.walk(curdir): if fichiers != []: print("Sous dossiers : %s" % sous_dossiers) for fichier in fichiers: try: convertir(dossier,fichier) except: continue rep = input("On efface les fichiers non codés en utf-8 et on les renomme ? (O / N) ATTENTION : plus de fichiers ISO ensuite !") if rep == 'O': for dossier, sous_dossiers, fichiers in os.walk(curdir): if fichiers !=[]: for fichier in fichiers: if os.path.exists(fichier) and os.path.exists("utf-"+fichier): suppression(dossier,fichier) else: if os.path.exists(fichier): print(fichier, "intact")
Ce code m’a paru beaucoup trop long pour le peu de chose qu’il doit faire. De plus, la commande iconv ne semblait pas trop fonctionner… J’ai donc écrit un petit programme tout bête.
Mon programme Python pour convertir l’encodage d’un fichier
# Auteur: Stéphane Pasquet # Site : https://mathweb.fr # Date : 2021/05/27 from os import walk, getcwd, mkdir from os.path import isdir from chardet import detect rep_courant = getcwd() directory_utf = rep_courant + '\\utf8' if not isdir(directory_utf): mkdir(directory_utf) for dossier, sous_dossiers, fichiers in walk(rep_courant): for fichier in fichiers: if fichier[-3:] == 'tex': d = rep_courant + '\\' + fichier fich = open(d,'rb') txt = fich.read() fich.close() codage = detect(txt)['encoding'] if codage != 'utf-8': Fichier = open(d , 'r') contenu = "" for ligne in Fichier.read(): contenu += str(ligne) Fichier2 = open( directory_utf + '\\' + fichier , 'w' , encoding = 'utf-8') Fichier2.write( contenu ) Fichier2.close()
L’idée ici est de sauvegarder ce script Python dans le répertoire des fichiers à convertir, puis de parcourir ce répertoire: si on rencontre un fichier “.tex” (l’extension peut bien sûr être choisie à votre convenance) et si l’encodage n’est pas UTF-8, alors on l’ouvre en mode binaire et on réécrit son contenu dans un autre fichier qui sera sauvegardé en UTF-8 dans un répertoire (ici, nommé “utf8”).
Puisque tu sembles utiliser Linux, iconv sert à changer l’encodage d’un fichier, mais il existe aussi konwert qui fait le même boulot. Par exemple konwert any-utf8 monfichier.txt convertit monfichier.txt encodé en quelque chose (déterminé par konwert) vers utf8. Il permet même de convertir les codes HTML en utf8 ou l’inverse, par exemple é en é, ou en (ou vers) tout un tas d’autres formats exotiques (ascii, iso*, cp*, mac*, html* et même tex).
iconv et konwert sont installés chez moi et il est parfois plus pratique d’utiliser un script shell pour convertir une volée de fichiers plutôt que de passer par Python.
Je ne suis pas sous Linux, mais sous Windows 10. Effectivement, sous Linux, iconv fonctionne bien. Je ne connaissais pas konwert, mais c’est normal, n’étant plus linuxien depuis fort longtemps :-).
Mais sous windows, je n’ai pas eu vent d’une commande shell adéquate, ce qui est, en effet, bien plus pratique que de passer par python… quoi que…
C:\Users\MonRep> py monscriptreencode.py
ça marche pas mal non plus, à condition que le fichier Python contienne les bonnes instructions pour ré-encoder les fichiers courant du répertoire courant.
C’est peu étonnant qu’iconv ne soit pas de base dans Windows, il fait partie (dans Debian) du paquet libc-bin, un paquet GNU.
On peut néanmoins le trouver pour Windows dans Cygwin.