j'ai fait le week-end dernier un petit script de réencodage de toute une arborescence. Je viens de prendre le temps de faire une petite page web pour présenter et expliquer la chose : http://sebdeblinux.free.fr/.
Dites-moi ce que vous en pensez, si cela vous est utile et surtout vos suggestions d'améliorations ou rapports de bugs. J'insiste sur le fait de faire vos essais sur une copie de vos données.
Sébastien
Bonjour,
J'ai essayé ton programme, et il marche très bien sauf sur les noms de fichiers qui contiennent des espaces (je n'aime trop les espaces dans les noms de fichiers, mais j'ai des anciens fichiers qui en ont encore).
Donc je te suggèrerais de changer dans la ligne 95 les 2 occurences de $fic par des "$fic", ce qui résoud le problème.
A cette occasion, je me suis aperçu que j'avais plein de fichiers de type "us-ascii" qui refusent tous de devenir des UTF-8. J'ai cru comprendre en regardant sur internet que l'us-ascii est la même chose que UTF-8. C'est vrai, ça ?
J'ai trouvé sur le site http://sebdeblinux.free.fr/ un script pour convertir de l'iso-8859-1 en utf-8.
Je suppose d'ailleurs que les arguments doivent être inversés aux lignes :
21:FROM="UTF-8"
22:TO="iso-8859-1"
On devrait avoir :
21:FROM="iso-8859-1"
22:TO="UTF-8"
Je souhaiterais m'en servir pour convertir de l'iso-8859-15 en utf-8.
Je mets donc :
21:FROM="iso-8859-15"
22:TO="UTF-8"
Tout à l'air de bien se passer pour les noms de fichiers et de répertoire, mais comme vous le dites vous même :
# Attention : si liste trop longue ça peut planter
# TODO : passer par xargs --> man xargs
Et effectivement ça plante :
=============
Entree dans : 6Úme
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
./convertEnc_to_utf.sh: line 95: [: too many arguments
Sortie de : 6Úme
Fini
Je ne suis malheureusement pas assez compétent en bash pour modifier quoi que ce soit ; c'est pourquoi je laisse ce message pour savoir si quelqu'un a eu un peu de temps (dont je ne veux pas abuser) pour modifier le script afin qu'il fonctionne en toute circonstance.
Bonsoir, j'ai apporté quelques modifications dans le script pour régler le problème des listes de fichiers trop longues et du remplacement d'un fichier appartenant à root (voir page perso de seb)
Voici le résultat, les modifs et commentaires sont précédés de 3 # (###) pour les retrouver facilement.
Je n'ai pas pu le tester, pas de machine en UTF-8 sous la main..., donc il n'est pas impossible qu'il y ait une erreur dans les modifications.
Jacques
Code:
#!/bin/bash
#
# Conversion de toute une arborescence d'un encodage dans un autre.
# Exemple d'utilisation :
# mise à jour de sa distribution Linux de iso-8859-1 vers UTF-8
#
# Nécessite : convmv et iconv
#
# Utilisation :
# $ ./convertEnc.sh Documents/Divers
#
# IMPORTANT : faites une copie de vos donnees et travaillez sur cette copie !!
# (Je ne peux être tenu responsable si vous corrompez vos donnees, soyez prudents)
#
# Ce script ne demande qu'a etre ameliore...
#
# Sebastien de Boissieu (c) 2006
# $Id: convertEnc.sh,v 1.5 2006/10/22 14:18:50 sebastien Exp $
# Licence : GPL 2
FROM="UTF-8"
TO="iso-8859-1"
echo "Conversion de $FROM en $TO"
# Procedure pour renommer un fichier si nom deja existant
renomme()
{
nbe=0
num="_$nbe"
nouvnom="$1"
while [ -e "$nouvnom" ];
do
let nbe=nbe+1
num="_$nbe"
nouvnom="$1$num"
done
export nouvnom
}
# Conversion recursive des noms de fichiers et repertoires
convert_names()
{
echo "Conversion des NOMS de fichiers et repertoires"
#convmv -r -f $FROM -t $TO --qfrom --qto --notest $1
### Protection contre les espaces
### convmv -r -f $FROM -t $TO --notest $1
convmv -r -f $FROM -t $TO --notest "$1"
echo ""
}
# Routine de conversion du contenu d'un fichier
do_convert()
{
fic="$1"
echo " Fichier $fic"
# Lecture du type mime
encForm=`file -bi "$fic" | awk -F "charset=" '{ print $2 }'`
if [ ! "$encForm" = "" ]; then
# le fichier possede un charset
echo " -> $encForm"
if [ ! "$encForm" = "$TO" ]; then
# ce charset est different de celui vise
# nom du fichier converti temporaire
renomme "$fic"_"$TO"
### Protection si le nom de $nouvnom contient des espaces
### nouv_fic=$nouvnom
nouv_fic="$nouvnom"
# la conversion
iconv -f "$encForm" -t $TO "$fic" -o "$nouv_fic"
# Pour conserver la/les date(s) :
touch -r "$fic" "$nouv_fic"
# Pour conserver le proprietaire
chown --reference "$fic" "$nouv_fic"
# pour conserver les droits :
chmod --reference "$fic" "$nouv_fic"
# on ecrase l'ancien fichier par le nouveau
### mv -f "$nouv_fic" "$fic"
if [ -w "$fic" ] ; then
### Sur mes tests, si le fichier n'est pas accessible en écriture
### un mv -f sur le fichier remplace pourtant celui-ci (droits d'écriture dans le répertoire)
mv -f "$nouv_fic" "$fic"
else
echo "Le fichier $fic n'est pas accessible en ecriture"
echo "Le fichier converti se nomme $nouv_fic"
fi
fi
fi
}
# Conversion recursive du contenu des fichiers texte
convert_content()
{
#echo "Conversion du contenu des fichiers"
if [ -d "$1" ]; then
# c'est un repertoire
if [ -x "$1" ]; then
# On peut entrer dans le repertoire
echo "Entree dans : $1"
### Protection si le répertoire contient un espace
### chemin_orig=`pwd`
chemin_orig="`pwd`"
cd -- "$1"
# liste complete (avec fichiers caches)
# Attention : si liste trop longue ça peut planter
# TODO : passer par xargs --> man xargs
### for fic in * .* ; do
for fic in * .* | xargs ; do
if [ $fic != "." -a $fic != ".." ]; then
base_fic=$(basename -- "$fic")
#echo "$fic -> $base_fic"
echo " Analyse de : $base_fic"
# recursivite
if [ -d "$base_fic" ]; then
# Si repertoire, on execute la procedure dessus
convert_content "$base_fic"
else
# sinon on fait la conversion
do_convert "$base_fic"
fi
fi
done
echo "Sortie de : $1"
### Idem
### cd $chemin_orig
cd "$chemin_orig"
else
echo "Entree INTERDITE dans : $1"
fi
else
# On fait la conversion sur le fichier
do_convert "$1"
fi
}
#=======================================
# Debut execution
### Alerte avant lancement du script
clear
echo -e "\n\nATTENTION : ne travaillez jamais sur les donnees d'origine !"
echo -e "\nEtes-vous certain de vouloir modifier ces fichiers ?"
echo -e "\tAppuyez sur Ctrl-C pour annuler ou sur Return pour continuer \c"
read Tempo
echo
### Fin de l'alerte
if [ $# -gt 0 ]; then
# pour l'instant on ne considere que le 1er argument
echo "Sur: $1"
echo ""
### On n'est pas à l'abri d'un répertoire avec des espaces dans le nom
### convert_names $1
convert_names "$1"
echo "============="
# Remarque : si $1 est un repertoire dont le nom a ete converti
# le contenu de $1 est obsolète.
# on le converti :
### Idem
### nom=$(echo $1 | iconv -f $FROM -t $TO)
nom=$(echo "$1" | iconv -f $FROM -t $TO)
### Idem
convert_content $nom
convert_content "$nom"
echo "Fini"
else
echo "Utilisation :"
echo "$0 chemin/repertoire"
### Alerte par précaution
echo "Ne travaillez jamais sur les donnees d'origine mais seulement sur une copie de celles-ci"
fi
merci JacquesF pour tes modifications !
Malheureusement la commande xargs plante :
Code:
convertEnc.sh: line 110: syntax error near unexpected token `|'
convertEnc.sh: line 110: ` for fic in * .* | xargs ; do'
la commande est :
Code:
for fic in * .* | xargs ; do
A vrai dire je n'y comprends rien à xargs et le man n'aide pas vraiment...
D'après ce que je trouve sur Internet il ne faut pas utiliser xargs dans la commande for mais générer la liste puis envoyer vers xargs dans un pipe.
Je creuse çà...
avec analyse_fichier qui contient le code de la boucle :
Code:
analyse_fichier()
{
$fic="$1"
if [ $fic != "." -a $fic != ".." ]; then
base_fic=$(basename -- "$fic")
#echo "$fic -> $base_fic"
echo " Analyse de : $base_fic"
# recursivite
if [ -d "$base_fic" ]; then
# Si repertoire, on execute la procedure dessus
convert_content "$base_fic"
else
# sinon on fait la conversion
do_convert "$base_fic"
fi
fi
}
Mais xargs ne veut pas d'une routine définie en interne...
Quote:
xargs: analyse_fichier: Aucun fichier ou répertoire de ce type
Et si on la définit dans un fichier externe en l'appelant de cette manière :
$fic="$1"
if [ $fic != "." -a $fic != ".." ]; then
base_fic=$(basename -- "$fic")
#echo "$fic -> $base_fic"
echo " Analyse de : $base_fic"
# recursivite
if [ -d "$base_fic" ]; then
# Si repertoire, on execute la procedure dessus
convert_content "$base_fic"
else
# sinon on fait la conversion
do_convert "$base_fic"
fi
fi
çà ne marche pas non plus :
Quote:
ConversionEncodage/analyse_fichier.sh: line 3: =.: command not found
ConversionEncodage/analyse_fichier.sh: line 4: [: too many arguments
En passant l'option -t à xargs on voit qu'il envoye toute la liste de fichiers d'un coup.
Edit:
Je me rends compte qu'il faudra déménager les fonctions appelées : do_convert et convert_content et au passage je casse la récursivité... (argh !)
Je laisse tomber pour ce soir on verra plus tard...
Il y a une façon de contourner le problème (j'utilise xargs sans soucis de cette façon, mais je n'ai aucun nom avec des espaces dans les répertoires concernés).
Se placer dans le répertoire voulu : cd MonRepertoire
Créer la liste des fichiers en redirigeant le tout dans un fichier, pour éviter de voir apparaître ce fichier dans la liste, le placer dans un autre répertoire ou sinon mettre un test dans la boucle pour ne rien faire si le fichier à analyser est celui contenant la liste : ls -a > /AutreRep/MaListe
Modifier la boucle de traitement des fichiers de cette façon :
while read File ; do
#Traitement du fichier en prenant soin de le placer entre guillemets
analyse_fichier "$File"
done < /AutreRep/MaListe
Cela devrait régler le problème d'une liste trop longue puisque qu'on n'applique la procédure que fichier par fichier.
Suite à une autre discussion, voilà un autre script qui transforme le contenu (uniquement) d'un fichier en iso-8859-15 en utf-8, si ça peut aider ....
Un problème est cependant contourné :
l'iso-8859-15 est en fait reconnu par "file -i" comme de l'iso-8859-1 (et c'est voulu car je n'ai que de l'iso-8859-15 et pas d'iso-8859-1).
Apparemment, il n'y a pas de commande permettant de distinguer l'iso-8859-1 de l'iso-8859-15.
Donc si un fichier est réllement en iso-8859-1, il sera converti comme de l'iso-8859-15 (donc avec des erreurs).
Par ailleurs, je réitère une autre question ;:
Les arguments doivent être inversés : aux lignes :
21:FROM="UTF-8"
22:TO="iso-8859-1"
On devrait avoir :
21:FROM="iso-8859-1"
22:TO="UTF-8"
non ?
#!/bin/sh
#script de limax
#version 3
#transforme les iso-8859-1 comme si cétait des iso-8859-15 !
function transforme()
{
char=`file -i $1 | sed 's/^.*charset=//'` #récupère le charset du fichier
if [ $char = iso-8859-1 ]
then
iconv -f iso-8859-15 -t utf-8 < $1 > $1.8 #conversion en utf8
mv $1.8 $1
echo "$1 a été transformé en utf8"
else
echo "$1 n'est pas iso-8859-15 mais "$char
fi
if [ $char = iso-8859-15 ]
then
iconv -f iso-8859-15 -t utf-8 < $1 > $1.8 #conversion en utf8
mv $1.8 $1
echo "$1 a été transformé en utf8"
else
echo "$1 n'est pas iso-8859-15 mais "$char
fi
}
function usage()
{
echo "Usage: $0 nom_du_fichier.txt"
echo "Ce programme transforme un fichier de charset iso-8859-15 en utf8"
echo "option -r pour convertir un dossier récurssivement"
echo "option -tr pour tester un dossier récurssivement"
echo "option -t pour tester un fichier"
exit 1
}
if [ $# \< 1 ] # si le nombre de paramètres n'est pas 1
then # affiche l'usage
usage
fi
case $1 in
-h | --help ) usage;;
-r | -R ) IFS=$'\n\t'
for i in `find ./ -type f `
do
transforme $i
done
;;
-t[rR] | -[rR]t ) IFS=$'\n\t'
for i in `find ./ -type f `
do
echo "$i est de type `file -i $i | sed 's/^.*charset=//'`"
done;;
-t ) IFS=$'\n\t'
i=`echo $* | cut -d" " -f2-`
echo "$i est de type `file -i $i | sed 's/^.*charset=//'`"
;;
* ) IFS=$'\n\t'
for i in $*
do
transforme $i
done;;
esac
unset IFS
Par ailleurs, je réitère une autre question ;:
Les arguments doivent être inversés : aux lignes :
21:FROM="UTF-8"
22:TO="iso-8859-1"
On devrait avoir :
21:FROM="iso-8859-1"
22:TO="UTF-8"
non ?
oui, oui bien sûr.
En fait pour mes tests je devais faire une conversion puis l'inverse pour remettre dans l'état initial. Et j'ai oublié de remettre l'ordre correct. Mais bon, les noms de variables sont explicites...
Vu qu'hier j'essayais de régler le problème de liste trop longue sans y parvenir je n'ai pas pu sortir un script corrigé...
Il y a aussi un autre souci qui vient peut-être de l'iso-8859-1 / iso-8859-15 : si la conversion plante le fichier n'est pas complet et ensuite le renommage écrase l'ancien fichier complet par le nouveau fichier incomplet ... glups ! Avec "$?" on devrait détecter un échec de iconv et ne pas renommer. Je l'ai implémenté rester à retrouver un cas qui fait planter pour tester.
Bonjour,
je suis en train de me "battre" avec le script de http://sebdeblinux.free.fr/, j'ai corrigé FROM - TO à la mano mais j'avoue être complètement dépassée par le reste des modifs ''
Je ne suis pas à la hauteur de Jacques F ou de Sebdeb. D'ailleurs mon but n'est pas de programmer des scripts mais de les utiliser...
J'ai pas mal de fichiers à convertir donc je peux tester si vous aviez des mises à jour à me transmettre.
Un conseil: ouvre un post spécifique pour ton problème, si tout est mélangé ça ne sera pas super.
Après explique quel est ton problème, ce que tu as fait...
je suis désolé de n'avoir pas fourni de version à jour de ma script mais :
1. je n'ai plus beaucoup de temps à y consacrer
2. j'ai eu des soucis avec la fonction xargs : je ne me souviens plus des détails car cela date du mois de novembre.
J'ai mis sur mon site http://sebdeblinux.free.fr/ la dernière version mais je ne suis pas certain qu'elle fonctionne bien (je suis même assez convaincu de l'inverse vu que je l'avais mise de côté
Enfin si cela peut vous aider... Bon courage en tout cas.
J'essaierai de me repencher dessus si j'ai le temps.
Qqn connait recode ?
Il rendrait iconv, dos2unix ou unix2dos obsolètes
Qlqs options :
recode -l | less Show available conversions (aliases on each line)
recode windows-1252.. file_to_change.txt Windows "ansi" to local charset (auto does CRLF conversion)
recode utf-8/CRLF.. file_to_change.txt Windows utf8 to local charset
recode iso-8859-15..utf8 file_to_change.txt Latin9 (western europe) to utf8
recode ../b64 < file.txt > file.b64 Base64 encode
recode /qp.. < file.txt > file.qp Quoted printable decode
recode ..HTML < file.txt > file.html Text to HTML
recode -lf windows-1252 | grep euro Lookup table of characters
echo -n 0x80 | recode latin-9/x1..dump Show what a code represents in latin-9 charmap
echo -n 0x20AC | recode ucs-2/x2..latin-9/x Show latin-9 encoding
echo -n 0x20AC | recode ucs-2/x2..utf-8/x Show utf-8 encoding
Dispo sous Mandriva :
Quote:
Name : recode
Packager : Oden Eriksson <oeriksson@mandriva.com>
URL : http://recode.progiciels-bpi.ca/
Summary : GNU recode
Description :
The GNU recode utility converts files between various character sets.
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum