web-dev-qa-db-fra.com

Conversion par lots de fichiers latin-1 en utf-8 en utilisant iconv

J'ai ce projet PHP sur mon OSX, qui est en codage latin1. Maintenant, j'ai besoin de 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 de répertoires et cela me charge énormément d'erreurs lors de l'exécution. Quelqu'un peut-il trouver une solution soignée?

26
Jasmo

Vous ne devriez pas utiliser ls comme cela et une boucle for n'est pas appropriée non plus. En outre, le répertoire de destination doit ê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.

Modifier:

La version iconv de OS X ne possède pas l'option -o. Essaye ça:

find . -type f -exec bash -c 'iconv -f iso-8859-1 -t utf-8 "{}" > /path/to/destination/"{}"' \;
36
Dennis Williamson

Quelques bonnes réponses, mais j'ai trouvé cela beaucoup plus facile dans mon cas avec un répertoire imbriqué de centaines de fichiers à convertir:

AVERTISSEMENT: ceci écrira les fichiers en place, alors faites une sauvegarde

$ vim $(find . -type f)

# in vim, go into command mode (:)
:set nomore
:bufdo set fileencoding=utf8 | w
13
cmcginty

Ceci convertit tous les fichiers avec l'extension .php du nom de fichier - dans le répertoire actuel 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 "{}" \;

Remarques: 

Pour obtenir une liste des fichiers qui seront ciblés au préalable, exécutez la commande sans les indicateurs -exec (comme ceci: find . -name "*.php"). Faire une sauvegarde est une bonne idée.

Utiliser sh comme ceci permet de canaliser et de rediriger avec -exec, ce qui est nécessaire car toutes les versions de iconv ne prennent pas en charge l'indicateur -o

Ajouter .utf8 au nom de fichier de la sortie puis le supprimer peut sembler étrange, mais cela est nécessaire. L'utilisation du même nom pour les fichiers de sortie et d'entrée peut provoquer les problèmes suivants:

  • Pour les gros fichiers (environ 30 Ko selon mon expérience), cela provoque un vidage mémoire (ou termination by signal 7)

  • Certaines versions de 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é par un fichier vide avant sa lecture.

9
UTF_or_Death

Pour convertir une arborescence de répertoires complète de l'iso-8859-1 à utf-8, y compris la création de sous-répertoires, aucune des solutions courtes ci-dessus ne fonctionnait pour moi car la structure de répertoires n'était pas créée dans la cible. Basé sur la réponse de Dennis Williamson, j'ai proposé 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 créera un clone de la sous-arborescence du répertoire en cours dans /tmp/dest (à adapter selon vos besoins), y compris tous les sous-répertoires et avec tous les fichiers iso-8859-1 convertis en utf-8. Testé sur macosx.

Btw: Vérifiez vos encodages de fichiers avec:

file -I file.php

pour obtenir les informations de codage.

J'espère que cela t'aides.

7
george g

Je crée le script suivant qui (i) sauvegarde tous les fichiers tex du répertoire "converti", (ii) vérifie le codage de chaque fichier tex et (iii) convertit en UTF-8 uniquement les fichiers tex de l'ISO-8859-1 codage.

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
5
Ricardo Terra

Si tous les fichiers que vous devez convertir sont des fichiers .php, vous pouvez utiliser les éléments suivants, qui sont récursifs par défaut:

for a in $(find . -name "*.php"); do iconv -f iso-8859-1 -t utf-8 <"$a" >new/"$a" ; done

Je crois que vos erreurs sont dues au fait que ls -R génère également une sortie qui pourrait ne pas être reconnue par iconv comme un nom de fichier valide, quelque chose comme ./my/dir/structure:.

4
Alberto Zaccagni

Sur unix.stackexchange.com, une question similaire a été posée, et le manuel de l'utilisateur suggère de recoder ce qui fait très bien l'affaire.

Je l'utilise pour convertir ucs-2 en utf-8 en place

recode ucs-2..utf-8 *.txt
4
Scott

Utilisez mkdir -p "${a%/*}"; avant iconv.

Notez que vous utilisez une construction for potentiellement dangereuse lorsqu'il existe des espaces dans les noms de fichiers, voir http://porkmail.org/era/unix/award.html .

1
user502515

En utilisant les réponses de Dennis Williamson et Alberto Zaccagni, j'ai développé le script suivant qui convertit tous les fichiers du type de fichier spécifié dans tous les sous-répertoires. La sortie est ensuite collectée dans un dossier 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.

Alternative (utilisateur interactif): .__ Maintenant, j'ai également créé un script utilisateur interactif qui vous permet de décider si vous souhaitez écraser les anciens fichiers ou simplement les renommer. Un merci supplémentaire à 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

Amusez-vous avec cela et je vous serais reconnaissant de tout commentaire pour l'améliorer, merci!

0
tc88
find . -iname "*.php" | xargs -I {} echo "iconv -f ISO-8859-1 -t UTF-8 \"{}\" > \"{}-utf8.php\""
0
calebern

Tout va bien avec les réponses ci-dessus, mais s’il s’agit d’un projet "mixte", c’est-à-dire qu’il existe déjà des fichiers UTF8, il est possible que nous ayons des problèmes. Voici donc ma solution.

#!/bin/bash
# file name: to_utf8

# current encoding:
encoding=$(file -i "$1" | sed "s/.*charset=\(.*\)$/\1/")

if [  "${encoding}" = "iso-8859-1" ] || [ "${encoding}" = "iso-8859-2" ]; 
then
echo "recoding from ${encoding} to UTF-8 file : $1"
recode ISO-8859-2..UTF-8 "$1"
fi

#example:
#find . -name "*.php" -exec to_utf8 {} \;
0
konrad_firm