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?

25
demandé sur julienc 2010-12-28 11:24:34

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/"{}"' \;
34
répondu Dennis Williamson 2010-12-28 14:53:37

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
12
répondu cmcginty 2016-07-05 20:08:59

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.

8
répondu UTF_or_Death 2018-05-31 12:24:17

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.

7
répondu george g 2015-06-27 09:05:15

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
5
répondu Ricardo Terra 2015-11-30 22:25:21

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
4
répondu Scott 2017-08-23 22:51:41

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:

3
répondu Alberto Zaccagni 2010-12-28 08:45:18

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 .

1
répondu user502515 2015-07-13 13:00:43

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!

0
répondu tc88 2015-04-15 09:11:52

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 {} \;
0
répondu konrad_firm 2016-04-04 10:46:54
find . -iname "*.php" | xargs -I {} echo "iconv -f ISO-8859-1 -t UTF-8 \"{}\" > \"{}-utf8.php\""
0
répondu calebern 2016-06-15 09:48:41