it-swarm.it

Come posso fare in modo che iconv sostituisca il file di input con l'output convertito?

Ho uno script bash che elenca tutti i file * .php in una directory e applica iconv ad esso. Questo ottiene output in STDOUT.

Dall'aggiunta di -o parametro (nella mia esperienza) in realtà scrive un file vuoto probabilmente prima che abbia luogo la conversione, come posso regolare il mio script in modo che faccia la conversione, quindi sovrascrive il file di input?

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

Questo non funziona perché iconv crea prima il file di output (poiché il file esiste già, lo tronca), quindi inizia a leggere il suo file di input (che ora è vuoto). La maggior parte dei programmi si comporta in questo modo.

Crea un nuovo file temporaneo per l'output, quindi spostalo in posizione.

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

Se iconv della tua piattaforma non ha -o, puoi utilizzare un reindirizzamento Shell con lo stesso effetto.

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

l'utilità sponge di Colin Watson (inclusa in Moreutils di Joey Hess ) automatizza questo:

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

Questa risposta si applica non solo a iconv ma a qualsiasi programma di filtro. Vale la pena ricordare alcuni casi speciali:

  • GNU sed e Perl -p avere un -i opzione per sostituire i file in atto.
  • Se il tuo file è estremamente grande, il tuo filtro sta solo modificando o rimuovendo alcune parti ma non aggiungendo mai cose (ad esempio grep, tr, sed 's/long input text/shorter text/') e ti piace vivere pericolosamente, potresti voler davvero modificare il file in posizione (le altre soluzioni menzionate qui creano un nuovo file di output e lo spostano in posizione alla fine, quindi l'originale i dati rimangono invariati se il comando viene interrotto per qualsiasi motivo).

Un'alternativa è recode, che utilizza la libreria libiconv per alcune conversioni. Il suo comportamento è sostituire il file di input con l'output, quindi funzionerà:

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

Poiché recode accetta più file di input come parametro, puoi risparmiare il ciclo for:

recode cp1251..utf8 *.php
61
manatwork

Per adesso

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

funziona come un fascino

4
galeksandrp

Puoi usare Vim in modalità Ex:

ex -sc '%!iconv -f cp1251 -t utf8' -cx "$file"
  1. % seleziona tutte le righe

  2. ! esegui comando

  3. x salva e chiudi

1
Steven Penny

Un'opzione è usare l'interfaccia di Perl su iconv e il suo -i modalità per la modifica sul posto:

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

Con GNU awk, puoi anche fare qualcosa del tipo:

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

Il ksh93 Shell ha anche un >; operatore per ciò che memorizza l'output in un file temporaneo che viene rinominato nel file reindirizzato se il comando ha avuto esito positivo:

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

Ecco un semplice esempio . Dovrebbe darti informazioni sufficienti per iniziare.

#!/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"

per me va bene

0
CoNsTaR

Puoi usare find, almeno questo ha funzionato per me su Raspbian Stretch:

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