Tengo un script bash que enumera todos los archivos *.php en un directorio y aplica iconv
lo. Esto obtiene salida en STDOUT.
Desde que se agregó el -o
El parámetro (en mi experiencia) en realidad escribe un archivo en blanco probablemente antes de que se realice la conversión, ¿cómo puedo ajustar mi secuencia de comandos para que realice la conversión y luego sobrescriba el archivo de entrada?
for file in *.php
do
iconv -f cp1251 -t utf8 "$file"
done
Respuesta aceptada:
Esto no funciona porque iconv
primero crea el archivo de salida (dado que el archivo ya existe, lo trunca), luego comienza a leer su archivo de entrada (que ahora está vacío). La mayoría de los programas se comportan de esta manera.
Cree un nuevo archivo temporal para la salida y luego muévalo a su lugar.
for file in *.php
do
iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
mv -f "$file.new" "$file"
done
Si el iconv
de su plataforma no tiene -o
, puede usar una redirección de shell con el mismo efecto.
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
mv -f "$file.new" "$file"
done
La sponge
de Colin Watson La utilidad (incluida en moreutils de Joey Hess) automatiza esto:
for file in *.php
do
iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done
Esta respuesta se aplica no solo a iconv
pero a cualquier programa de filtro. Vale la pena mencionar algunos casos especiales:
- GNU sed y Perl
-p
tener un-i
opción para reemplazar archivos en su lugar. - Si su archivo es extremadamente grande, su filtro solo modifica o elimina algunas partes pero nunca agrega cosas (por ejemplo,
grep
,tr
,sed 's/long input text/shorter text/'
), y le gusta vivir peligrosamente, es posible que desee modificar genuinamente el archivo en su lugar (las otras soluciones mencionadas aquí crean un nuevo archivo de salida y lo mueven a su lugar al final, por lo que los datos originales no se modifican si el comando se interrumpe por cualquier motivo).