Ho uno script bash che enumera ogni file *.php in una directory e applica iconv
ad esso. Questo ottiene l'output in STDOUT.
Da quando ho aggiunto il -o
parametro (nella mia esperienza) in realtà scrive un file vuoto probabilmente prima che avvenga la conversione, come posso regolare il mio script in modo che esegua la conversione, quindi sovrascrive il file di input?
for file in *.php
do
iconv -f cp1251 -t utf8 "$file"
done
Risposta accettata:
Non funziona perché iconv
prima crea 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 della shell con lo stesso effetto.
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
mv -f "$file.new" "$file"
done
La sponge
di Colin Watson l'utilità (inclusa in moreutils di Joey Hess) automatizza questo:
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done
Questa risposta non si applica 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 elementi (ad es.
grep
,tr
,sed 's/long input text/shorter text/'
), e ti piace vivere pericolosamente, potresti voler modificare davvero il file sul posto (le altre soluzioni qui menzionate creano un nuovo file di output e lo spostano al suo posto alla fine, quindi i dati originali rimangono invariati se il comando viene interrotto per qualsiasi motivo).