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.