Conversion par lots de fichiers latins-1 en utf-8 en utilisant iconv
j'ai ce projet PHP sur mon OSX qui est en latin1-encoding. Maintenant, je dois convertir des fichiers en UTF8. Je ne suis pas vraiment un codeur shell et j'ai essayé quelque chose que j'ai trouvé sur internet:
mkdir new
for a in `ls -R *`; do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done
mais cela ne crée pas la structure du répertoire et cela me donne un tas d'erreurs lors de l'exécution. Quelqu'un peut-il venir avec la solution élégante?
11 réponses
vous ne devriez pas utiliser ls
comme ça et une boucle for
n'est pas appropriée non plus. De plus, le répertoire de destination devrait être en dehors du répertoire source.
mkdir /path/to/destination
find . -type f -exec iconv -f iso-8859-1 -t utf-8 "{}" -o /path/to/destination/"{}" \;
pas besoin de boucle. L'option -type f
inclut les fichiers et exclut les répertoires.
Edit:
la version OS X de iconv
n'a pas l'option -o
. Essayez ceci:
find . -type f -exec bash -c 'iconv -f iso-8859-1 -t utf-8 "{}" > /path/to/destination/"{}"' \;
Quelques bonnes réponses, mais j'ai trouvé cela beaucoup plus facile dans mon cas, avec un sous répertoire de centaines de fichiers à convertir:
avertissement: cela écrira les fichiers en place, donc faire une sauvegarde
$ vim $(find . -type f)
# in vim, go into command mode (:)
:set nomore
:bufdo set fileencoding=utf8 | w
convertit tous les fichiers avec l'extension .php
du nom de fichier - dans le répertoire courant et ses sous-répertoires-en préservant la structure du répertoire:
find . -name "*.php" -exec sh -c "iconv -f ISO-8859-1 -t UTF-8 {} > {}.utf8" \; -exec mv "{}".utf8 "{}" \;
Notes:
pour obtenir une liste des fichiers qui seront ciblés à l'avance, il suffit d'exécuter la commande sans les drapeaux -exec
(comme ceci: find . -name "*.php"
). Faire une sauvegarde est une bonne idée.
en utilisant sh
comme ceci permet la tuyauterie et redirection avec -exec, ce qui est nécessaire car toutes les versions d'iconv ne supportent pas le drapeau -o
.
ajouter .utf8
au nom de fichier de la sortie et ensuite l'enlever pourrait sembler étrange mais il est nécessaire. L'utilisation du même nom pour les fichiers de sortie et d'entrée peut causer les problèmes suivants:
-
pour les gros fichiers (environ 30 Ko d'après mon expérience) il provoque core dump (ou
termination by signal 7
) -
certaines versions d'iconv semblent créer le fichier de sortie avant de lire le fichier d'entrée, ce qui signifie que si les fichiers d'entrée et de sortie ont le même nom, le fichier d'entrée est écrasé avec un fichier vide avant qu'il ne soit lu.
pour convertir de façon récursive un arbre de répertoire complet de iso-8859-1 en utf-8 y compris la création de sous-répertoires aucune des solutions courtes ci-dessus n'a fonctionné pour moi parce que la structure de répertoire n'a pas été créée dans la cible. Sur la base de la réponse de Dennis Williamsons, j'ai trouvé la solution suivante:
find . -type f -exec bash -c 't="/tmp/dest"; mkdir -p "$t/`dirname {}`"; iconv -f iso-8859-1 -t utf-8 "{}" > "$t/{}"' \;
il va créer un clone du sous-répertoire courant dans /tmp/dest
(ajuster à vos besoins) y compris tous les sous-répertoires et avec tous les iso-8859-1
fichiers convertis en utf-8
. Testé sur macosx.
Btw: Vérifiez vos encodages de fichier avec:
file -I file.php
pour obtenir les informations d'encodage.
Espérons que cette aide.
je crée le script suivant qui (i) sauvegarde tous les fichiers tex dans le répertoire" converti", (ii) vérifie l'encodage de chaque fichier tex, et (iii) convertit en UTF-8 seulement les fichiers tex dans L'encodage ISO-8859-1.
FILES=*.tex
for f in $FILES
do
filename="${f%.*}"
echo -n "$f"
#file -I $f
if file -I $f | grep -wq "iso-8859-1"
then
mkdir -p converted
cp $f ./converted
iconv -f ISO-8859-1 -t UTF-8 $f > "${filename}_utf8.tex"
mv "${filename}_utf8.tex" $f
echo ": CONVERTED TO UTF-8."
else
echo ": UTF-8 ALREADY."
fi
done
sur unix.stackexchange.com une question similaire a été posée, et l'utilisateur manatwork suggéré recode qui fait le tour très bien.
Je l'ai utilisé pour convertir ucs-2 en utf-8 en place
recode ucs-2..utf-8 *.txt
Si tous les fichiers que vous avez à convertir sont .php vous pouvez utiliser ce qui suit, qui est récursif par défaut:
for a in $(find . -name "*.php"); do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done
je pense que vos erreurs étaient dues au fait que ls -R
produit aussi une sortie qui pourrait ne pas être reconnue par iconv comme un nom de fichier valide, quelque chose comme ./my/dir/structure:
utiliser mkdir -p "${a%/*}";
avant iconv.
notez que vous utilisez une construction potentiellement dangereuse for
quand il y a des espaces dans les noms de fichiers, voir http://porkmail.org/era/unix/award.html .
en utilisant les réponses de Dennis Williamson et Alberto Zaccagni, j'ai créé le script suivant qui convertit tous les fichiers du type de fichier spécifié à partir de tous les sous-répertoires. La sortie est alors collectée dans un dossier qui est donné par /path/to/destination
mkdir /path/to/destination
for a in $(find . -name "*.php");
do
filename=$(basename $a);
echo $filename
iconv -f iso-8859-1 -t utf-8 <"$a" >"/path/to/destination/$filename";
done
la fonction basename renvoie le nom du fichier sans le chemin du fichier.
Alternatifs " (utilisateur interactif): Maintenant, j'ai aussi créé un utilisateur interactif script qui vous permet de décider si vous voulez réécrire les anciens fichiers ou simplement les renommer. Des remerciements supplémentaires vont à tbsalling
for a in $(find . -name "*.tex");
do
iconv -f iso-8859-1 -t utf-8 <"$a" >"$a".utf8 ;
done
echo "Should the original files be replaced (Y/N)?"
read replace
if [ "$replace" == "Y" ]; then
echo "Original files have been replaced."
for a in $(find . -name "*.tex.utf8");
do
file_no_suffix=$(basename -s .tex.utf8 "$a");
directory=$(dirname "$a");
mv "$a" "$directory"/"$file_no_suffix".tex;
done
else
echo "Original files have been converted and converted files were saved with suffix '.utf8'"
fi
en amuser et je serais reconnaissant pour tous les commentaires afin de l'améliorer, merci!
tout va bien avec les réponses ci-dessus, mais si c'est un projet "mixte", i.e. il y a déjà des fichiers UTF8, alors nous pouvons avoir des problèmes, donc voici ma solution, je vérifie d'abord l'encodage des fichiers.
#!/bin/bash
# file name: to_utf8
# current encoding:
encoding=$(file -i "" | sed "s/.*charset=\(.*\)$//")
if [ "${encoding}" = "iso-8859-1" ] || [ "${encoding}" = "iso-8859-2" ];
then
echo "recoding from ${encoding} to UTF-8 file : "
recode ISO-8859-2..UTF-8 ""
fi
#example:
#find . -name "*.php" -exec to_utf8 {} \;
find . -iname "*.php" | xargs -I {} echo "iconv -f ISO-8859-1 -t UTF-8 \"{}\" > \"{}-utf8.php\""