Modificando el contenido de varios ficheros a la vez con un sencillo sed + bucle while

Los administradores de Sistemas y Middleware tenemos que realizar cambios de configuración y modificar ficheros prácticamente a diario. Cuando hay una gran cantidad de ficheros que modificar puede resultar tedioso y quitarnos tiempo para otras tareas más creativas o interesantes. Para el ejemplo utilizaré nombres genéricos tanto para elementos a modificar como el nombre de los ficheros, ya que lo que interesa es que quede claro el concepto.

Pongamos como ejemplo que tengo que modicar una cadena de texto que pasa de ser mi_aplicacion a mi_aplicacion_revisada, otra cadena de números (IP) que pasa de ser 192.168.2.101 a 192.168.2.102 y una cadena alfanumérica que pasa de parametro1 a parametro2. Cada uno de esos cambios se tiene que hacer en cada uno de los siguientes ficheros:

/opt/mi_aplicacion/fichero1
/opt/mi_aplicacion/fichero2
/opt/mi_aplicacion/fichero3
/opt/mi_aplicacion/fichero4
/usr/local/mas_ficheros/fichero5
/usr/local/mas_ficheros/fichero6
/usr/local/mas_ficheros/fichero7
/var/lib/fichero8
/var/lib/fichero9
/var/lib/fichero10

Podríamos ir uno a uno modificándolos manualmente. Sin embargo, esto nos quitaría mucho tiempo. Una segunda solución sería también ir uno por uno pero realizando sustituciones con sed de la siguiente manera. Por ejemplo para /opt/mi_aplicacion/fichero1 podríamos realizar:

sed -i -e 's/192.168.2.101/192.168.2.102/g' /opt/mi_aplicacion/fichero1
sed -i -e 's/mi_aplicacion/mi_aplicacion_revisada/g' /opt/mi_aplicacion/fichero1
sed -i -e 's/parametro1/parametro2/g' /opt/mi_aplicacion/fichero1

Sin embargo, lo ideal sería automatizar este proceso para no perder demasiado tiempo en cada uno de los ficheros.

Introduzcamos todos esos paths a ficheros en un fichero que llamaremos file-list, y que contendrá un path por línea tal y como mostraba más arriba:

Ahora podríamos crear un bucle while para leer del fichero y realizar modificaciones sobre los ficheros iterando uno a uno sin tener que hacer mucho más.

#!/bin/bash

backup_date=$(date +%Y%m%d)

while read line;do
    file_name=$(basename $line)
    dir_name=$(dirname $line)
    cp $line $dir_name/${file_name}_${backup_date}
    sed -i -e 's/192.168.2.101/192.168.2.102/g' $line
    sed -i -e 's/mi_aplicacion/mi_aplicacion_revisada/g' $line
    sed -i -e 's/parametro1/parametro2/g' $line
done <$1

El snippet de código es muy simple y claro. Un poco de explicación sobre qué hace cada elemento:

  • backup_date=$(date +%Y%m%d) -> Sacamos el formato de la fecha que pondremos como sufijo a cada backup de fichero.
  • Las variables file_name y dir_name -> recogen el nombre de fichero y el path (directorio) en el que se encuentra respectivamente.
  • cp $line $dir_name/${file_name}_${backup_date} -> Realiza el backup del fichero que se modifica, dejando este backup en el mismo directorio en el que se encuentra el fichero original.
  • Los tres sed posteriores realizan las modificaciones pertinentes en el fichero que en ese momento está pasando por la iteración del while.
  • Respecto al bucle, leemos línea a línea con while read line y le pasamos el primer argumento como parámetro con done <$1. Ese primer argumento será el nombre del fichero donde tenemos la lista de ficheros a modificar. En nuestro caso file-list.

¿Cómo ejecutaremos el snippet? Considerando que hemos llamado al script sed-modifier.sh y pasándole la lista de ficheros file-list como parámetro de la siguiente manera:

./sed-modifier.sh file-list

Una vez lanzado ya tendremos nuestros ficheros modificados del tirón, con sus respectivos backups por si tuviéramos que dar marcha atrás.

Como vemos, una forma sencilla de ahorrarnos tiempo de trabajo en una tarea repetitiva que no nos aporta demasiado. Por supuesto habrá más formas de hacerlo, incluso en Python. Aunque habría que automatizarlo, por ejemplo en mi repositorio de GitHub tengo un script para sustituir un string por otro en un fichero. Este script se modificar de la misma manera, para recorrer con un bucle una lista de ficheros e ir realizando las modificaciones pertinentes.