web-dev-qa-db-fra.com

iconv tout encodage en UTF-8

J'essaie de pointer iconv vers un répertoire et tous les fichiers seront convertis en UTF-8 quel que soit l'encodage actuel

J'utilise ce script mais vous devez spécifier de quel encodage vous allez. Comment puis-je faire en sorte qu'il détecte automatiquement l'encodage actuel?

dir_iconv.sh

#!/bin/bash

ICONVBIN='/usr/bin/iconv' # path to iconv binary

if [ $# -lt 3 ]
then
    echo "$0 dir from_charset to_charset"
    exit
fi

for f in $1/*
do
    if test -f $f
    then
        echo -e "\nConverting $f"
        /bin/mv $f $f.old
        $ICONVBIN -f $2 -t $3 $f.old > $f
    else
        echo -e "\nSkipping $f - not a regular file";
    fi
done

ligne terminale

Sudo convert/dir_iconv.sh convert/books CURRENT_ENCODING utf8
19
Blainer

Peut-être que vous recherchez enca :

Enca est un analyseur de jeux de caractères extrêmement naïf. Il détecte le jeu de caractères et l'encodage des fichiers texte et peut également les convertir en d'autres encodages à l'aide d'un convertisseur intégré ou de bibliothèques et d'outils externes tels que libiconv, librecode ou cstocs.

Actuellement, il prend en charge le codage biélorusse, bulgare, croate, tchèque, estonien, hongrois, letton, lituanien, polonais, russe, slovaque, slovène, ukrainien, chinois et certains codages multi-octets indépendamment sur la langue.

Notez qu'en général, la détection automatique de l'encodage actuel est un processus difficile (la même séquence d'octets peut être un texte correct dans plusieurs encodages). enca utilise une heuristique basée sur la langue que vous lui dites de détecter (pour limiter le nombre d'encodages). Vous pouvez utiliser enconv pour convertir des fichiers texte en un seul encodage.

18
Michal Kottman

Vous pouvez obtenir ce dont vous avez besoin en utilisant le fichier utils gnu standard et awk. Exemple:

file -bi .xsession-errors me donne: "text/plain; charset = us-ascii"

alors file -bi .xsession-errors |awk -F "=" '{print $2}' me donne "us-ascii"

Je l'utilise dans des scripts comme ça:

CHARSET="$(file -bi "$i"|awk -F "=" '{print $2}')"

if [ "$CHARSET" != utf-8 ]; then

        iconv -f "$CHARSET" -t utf8 "$i" -o outfile

fi
10
Julian Hughes

Les compiler tous. Allez dans dir, créez dir2utf8.sh:

#!/bin/bash
# converting all files in a dir to utf8 

for f in *
do
    if test -f $f then
        echo -e "\nConverting $f"
        CHARSET="$( file -bi "$f"|awk -F "=" '{print $2}')"
        if [ "$CHARSET" != utf-8 ]; then
                iconv -f "$CHARSET" -t utf8 "$f" -o "$f"
        fi
    else
        echo -e "\nSkipping $f - it's a regular file";
    fi
done
6

Voici ma solution pour placer tous les fichiers:

#!/bin/bash

apt-get -y install recode uchardet > /dev/null
find "$1" -type f | while read FFN # 'dir' should be changed...
do
    encoding=$(uchardet "$FFN")
    echo "$FFN: $encoding"
    enc=`echo $encoding | sed 's#^x-mac-#mac#'`
    set +x
    recode $enc..UTF-8 "$FFN"
done

https://Gist.github.com/demofly/25f856a96c29b89baa32

mettre dans convert-dir-to-utf8.sh et courir:

bash convert-dir-to-utf8.sh /pat/to/my/trash/dir

Notez que sed est une solution de contournement pour les encodages mac ici. De nombreux encodages peu courants nécessitent des solutions de contournement comme celle-ci.

4
demofly

Voici ma réponse ... = D


#!/bin/bash

find <YOUR_FOLDER_PATH> -name '*' -type f -exec grep -Iq . {} \; -print0 | 
while IFS= read -r -d $'\0' LINE_FILE; do
    CHARSET=$(uchardet $LINE_FILE)
    echo "Converting ($CHARSET) $LINE_FILE"

    # NOTE: Convert/reconvert to utf8. By Questor
    iconv -f "$CHARSET" -t utf8 "$LINE_FILE" -o "$LINE_FILE"

    # NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
    # [Refs.: https://stackoverflow.com/a/2223926/3223785 ,
    # https://stackoverflow.com/a/45240995/3223785 ]
    sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"

done
# [Refs.: https://justrocketscience.com/post/handle-encodings , 
# https://stackoverflow.com/a/9612232/3223785 , 
# https://stackoverflow.com/a/13659891/3223785 ]

QUESTION SUPPLÉMENTAIRE: Je ne sais pas si mon approche est la plus sûre. Je dis cela parce que j'ai remarqué que certains fichiers ne sont pas correctement convertis (les caractères seront perdus) ou sont "tronqués". Je soupçonne que cela a à voir avec l'outil "iconv" ou avec les informations de jeu de caractères obtenues avec l'outil "uchardet". J'étais curieux de connaître la solution présentée sur https://stackoverflow.com/a/22841847/3223785 (@demofly) car elle pourrait être plus sûre.


Une autre réponse, désormais basée sur la réponse de @demofly ...

#!/bin/bash

find <YOUR_FOLDER_PATH> -name '*' -type f -exec grep -Iq . {} \; -print0 | 
while IFS= read -r -d $'\0' LINE_FILE; do
    CHARSET=$(uchardet $LINE_FILE)
    REENCSED=`echo $CHARSET | sed 's#^x-mac-#mac#'`
    echo "\"$CHARSET\" \"$LINE_FILE\""

    # NOTE: Convert/reconvert to utf8. By Questor
    recode $REENCSED..UTF-8 "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP

    STDERR_OP=$(cat STDERR_OP)
    rm -f STDERR_OP
    if [ -n "$STDERR_OP" ] ; then

        # NOTE: Convert/reconvert to utf8. By Questor
        iconv -f "$CHARSET" -t utf8 "$LINE_FILE" -o "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP

        STDERR_OP=$(cat STDERR_OP)
        rm -f STDERR_OP
    fi

    # NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
    # [Refs.: https://stackoverflow.com/a/2223926/3223785 ,
    # https://stackoverflow.com/a/45240995/3223785 ]
    sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"

    if [ -n "$STDERR_OP" ] ; then
        echo "ERROR: \"$STDERR_OP\""
    fi
    STDOUT_OP=$(cat STDOUT_OP)
    rm -f STDOUT_OP
    if [ -n "$STDOUT_OP" ] ; then
        echo "RESULT: \"$STDOUT_OP\""
    fi
done
# [Refs.: https://justrocketscience.com/post/handle-encodings , 
# https://stackoverflow.com/a/9612232/3223785 , 
# https://stackoverflow.com/a/13659891/3223785 ]

Solution hybride avec recode et vim ...

#!/bin/bash

find <YOUR_FOLDER_PATH> -name '*' -type f -exec grep -Iq . {} \; -print0 | 
while IFS= read -r -d $'\0' LINE_FILE; do
    CHARSET=$(uchardet $LINE_FILE)
    REENCSED=`echo $CHARSET | sed 's#^x-mac-#mac#'`
    echo "\"$CHARSET\" \"$LINE_FILE\""

    # NOTE: Convert/reconvert to utf8. By Questor
    recode $REENCSED..UTF-8 "$LINE_FILE" 2> STDERR_OP 1> STDOUT_OP

    STDERR_OP=$(cat STDERR_OP)
    rm -f STDERR_OP
    if [ -n "$STDERR_OP" ] ; then

        # NOTE: Convert/reconvert to utf8. By Questor
        bash -c "</dev/tty vim -u NONE +\"set binary | set noeol | set nobomb | set encoding=utf-8 | set fileencoding=utf-8 | wq\" \"$LINE_FILE\""

    else

        # NOTE: Remove "BOM" if exists as it is unnecessary. By Questor
        # [Refs.: https://stackoverflow.com/a/2223926/3223785 ,
        # https://stackoverflow.com/a/45240995/3223785 ]
        sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE"

    fi
done

REMARQUE: C'était la solution avec le plus grand nombre de conversions parfaites. De plus, nous n'avions aucun fichier tronqué.


AVERTISSEMENT: Faites une sauvegarde de vos fichiers et utilisez un outil de fusion pour vérifier/comparer les modifications. Des problèmes vont probablement apparaître!

CONSEIL: La commande sed -i '1s/^\xEF\xBB\xBF//' "$LINE_FILE" peut être exécuté après une comparaison préliminaire avec l'outil de fusion après une conversion sans lui car il peut provoquer des "différences".

REMARQUE: La recherche utilisant "find" apporte tous les fichiers non binaires de "YOUR_FOLDER_PATH" et de ses sous-dossiers.

Merci!

1
Eduardo Lucio

Découvrez les outils disponibles pour une conversion de données dans une interface Linux: https://www.debian.org/doc/manuals/debian-reference/ch11.fr.html

De plus, il y a une quête pour trouver une liste complète des encodages disponibles dans iconv. Exécutez simplement iconv --list et découvrez que l'encodage des noms diffère des noms renvoyés par l'outil uchardet (par exemple: x-mac-cyrillic dans uchardet vs mac-cyrillic dans iconv)

0
demofly

la commande enca ne fonctionne pas pour mon fichier texte en chinois simplifié avec codage GB2312.

Au lieu de cela, j'utilise la fonction suivante pour convertir le fichier texte pour moi. Vous pouvez bien sûr rediriger la sortie vers un fichier.

Il nécessite des commandes chardet et iconv.

detection_cat () 
{
    DET_OUT=$(chardet $1);
    ENC=$(echo $DET_OUT | sed "s|^.*: \(.*\) (confid.*$|\1|");
    iconv -f $ENC $1
}
0
Jared Tsai