web-dev-qa-db-fra.com

Comment puis-je faire iconv remplacer le fichier d'entrée par la sortie convertie?

J'ai un script bash qui énumère tous les fichiers * .php d'un répertoire et y applique iconv. Cela obtient la sortie dans STDOUT.

Depuis l'ajout de -o paramètre (d'après mon expérience) écrit en fait un fichier vierge probablement avant la conversion, comment puis-je ajuster mon script pour qu'il effectue la conversion, puis écrase le fichier d'entrée?

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file"
done
73
meder omuraliev

Cela ne fonctionne pas car iconv crée d'abord le fichier de sortie (puisque le fichier existe déjà, il le tronque), puis commence à lire son fichier d'entrée (qui est maintenant vide). La plupart des programmes se comportent de cette façon.

Créez un nouveau fichier temporaire pour la sortie, puis déplacez-le en place.

for file in *.php
do
    iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
    mv -f "$file.new" "$file"
done

Si le iconv de votre plateforme n'a pas -o, vous pouvez utiliser une redirection Shell vers le même effet.

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
    mv -f "$file.new" "$file"
done

l'utilitaire sponge de Colin Watson (inclus dans Moreutils de Joey Hess ) automatise ceci:

for file in *.php
do
    iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done

Cette réponse s'applique non seulement à iconv mais à tout programme de filtrage. Quelques cas particuliers méritent d'être mentionnés:

  • GNU sed et Perl -p avoir un -i option pour remplacer les fichiers en place.
  • Si votre fichier est extrêmement volumineux, votre filtre modifie ou supprime uniquement certaines parties mais n'ajoute jamais d'éléments (par exemple grep, tr, sed 's/long input text/shorter text/'), et vous aimez vivre dangereusement, vous voudrez peut-être vraiment modifier le fichier en place (les autres solutions mentionnées ici créent un nouveau fichier de sortie et le mettent en place à la fin, donc l'original les données restent inchangées si la commande est interrompue pour une raison quelconque).

Une alternative est recode, qui utilise la bibliothèque libiconv pour certaines conversions. Son comportement consiste à remplacer le fichier d'entrée par la sortie, donc cela fonctionnera:

for file in *.php
do
    recode cp1251..utf8 "$file"
done

Comme recode accepte plusieurs fichiers d'entrée comme paramètre, vous pouvez épargner la boucle for:

recode cp1251..utf8 *.php
61
manatwork

Pour l'instant

find . -name '*.php' -exec iconv -f CP1251 -t UTF-8 {} -o {} \;

fonctionne comme un charme

4
galeksandrp

Vous pouvez utiliser Vim en mode Ex:

ex -sc '%!iconv -f cp1251 -t utf8' -cx "$file"
  1. % sélectionner toutes les lignes

  2. ! exécuter la commande

  3. x enregistrer et fermer

1
Steven Penny

Une option consiste à utiliser l'interface de Perl avec iconv et son -i mode d'édition sur place:

Perl -MText::Iconv -i -pe '
  BEGIN{$i=Text::Iconv->new(qw(cp1252 UTF-8));$i->raise_error(1)}
  $_ = $i->convert($_)' ./*.php

Avec GNU awk, vous pouvez également faire quelque chose comme:

gawk -v cmd='iconv -f cp1252 -t utf-8' -i inplace '
  {print | cmd}; ENDFILE {close(cmd)}' ./*.php

Le ksh93 Shell a également un >; opérateur pour celui qui stocke la sortie dans un fichier temporaire qui est renommé en fichier redirigé si la commande a réussi:

for f in *.php; do
  iconv -f cp1252 -t utf-8 < $f >; $f
done
0
Stéphane Chazelas

Voici un exemple simple . Il devrait vous donner suffisamment d'informations pour commencer.

#!/bin/bash
#conversor.sh
#Author.....: dede.exe
#E-mail.....: [email protected]
#Description: Convert all files to a another format
#             It's not a safe way to do it...
#             Just a desperate script to save my life...
#             Use it such a last resort...

to_format="utf8"
file_pattern="*.Java"

files=`find . -name "${file_pattern}"`

echo "==================== CONVERTING ===================="

#Try convert all files in the structure
for file_name in ${files}
do
        #Get file format
        file_format=`file $file_name --mime-encoding | cut -d":" -f2 | sed -e 's/ //g'`

        if [ $file_format != $to_format ]; then

                file_tmp="${unit_file}.tmp"

                #Rename the file to a temporary file
                mv $file_name $file_tmp

                #Create a new file with a new format.
                iconv -f $file_format -t $to_format $file_tmp > $file_name

                #Remove the temporary file
                rm $file_tmp

                echo "File Name...: $file_name"
                echo "From Format.: $file_format"
                echo "To Format...: $to_format"
                echo "---------------------------------------------------"

        fi
done;
0
dede.exe
echo "`iconv -f cp1251 -t utf8 $file`" > "$file"

travaille pour moi

0
CoNsTaR

Vous pouvez utiliser find, au moins cela a fonctionné pour moi sur Raspbian Stretch:

find . -type f -name '*php' -execdir iconv -f cp1251 -t UTF-8 '{}' -o '{}'.tmp \; -execdir mv '{}'.tmp '{}' \;
0
rannala