Sustituir contenido varios ficheros desde la terminal

como hacer cambios en varios ficheros desde la terminal de comandosAunque hace poco vimos cómo sustituir el contenido de un fichero de texto desde la linea de comandos familiarizándonos con el uso del comando sed y sus parámetros más habituales; se me ha presentando en el trabajo la necesidad de realizar automáticamente una serie de cambios en los ficheros de configuración de determinado proyecto web.

Como tener que hacerlo manualmente hubiese requerido el consejo de una buena asesoría contable o fiscal (por los gastos que supondría abordarlo), terminé jugando con la búsqueda recursiva de textos del comando grep y nuestro querido sed para evitar trabajo innecesario y posibles despistes (que de ésos todos tenemos alguno :()

Aplicar el cambio

El comando a utilizar sería

OLD="texto-descartado"; NEW="texto-deseado"; sed -i -e "s/${OLD}\b/${NEW}/gi" `grep -lir "$OLD\b" /directorio/del/proyecto`

En principio podría parecer complejo; descompongámoslo un poco para entenderlo mejor

  • OLD y NEW son dos variables que contienen, respectivamente, el texto que estamos buscando (OLD) y el texto por el que queremos sustituirlo (NEW)
  • grep es el encargado de buscar recursivamente (-r) los nombres de los ficheros (-l)  que contengan el texto que nos interesa ($OLD) sin tener en cuenta mayúsculas ni minúsculas (-i) en el directorio que le indiquemos con /directorio/del/proyecto
  • sed es el encargado de hacer las sustituciones (ver cómo utilizar sed en bash para refrescar la memoria y/o comprender mejor su funcionamiento). Obsérvese el uso de ${} para poder usar variables con sed.
NOTA: observa el uso de /b para que considere palabras completas; si no te interesa dicho comportamiento y buscar fragmentos de texto (aunque formen parte de otras palabras) quítalo.

Conclusión

Pequeña chuleta que estoy convencido voy a consultar más de una vez para poder realizar cambios rápidamente en los ficheros de texto de una carpeta desde Linux.

Espero que os resulte tan interesante y/o útil como a mi 🙂

8 comentarios en “Sustituir contenido varios ficheros desde la terminal

  1. Marcos Delgado dijo:

    Yo uso rpl:

    aptitude show rpl

    Paquete: rpl
    Nuevo: sí
    Estado: instalado
    Instalado automáticamente: no
    Versión: 1.5.5-1
    Prioridad: opcional
    Sección: utils
    Desarrollador: Kevin Coyner
    Tamaño sin comprimir: 86.0 k
    Depende de: python, python-support (>= 0.2)
    Descripción: intelligent recursive search/replace utility
    rpl is a text replacement utility. It will replace strings with new strings in multiple text files. It can work recursively
    over directories and supports limiting the search to specific file suffixes.

    Homepage: http://rpl.sourceforge.net/

    • Interesante script, lo dejo anotado para posibles usos futuros.
      Aunque siempre es interesante no depender de terceras aplicaciones por si no cuentas con ella (o no tienes permiso para instalarla) en la máquina en la que estés 😉

      • Marcos Delgado dijo:

        Sí, estoy de acuerdo, pero es que ese script me hizo la vida sencilla cuando iniciaba en GNU/linux, y no sabía nada de patrones y esas cosas raras. Al rato te paso una opción con perl, la que uso en el servidor donde actualizo información y donde NO puedo instalar nada 😛
        Saludos.

  2. helq dijo:

    Muy buena info, muchas gracias. Ven pero tengo una inquietud, he usado el comando que haz dado (pero le cambié /gi por sólo /g), para un script, específicamente un PKGBUILD de ArchLinux en que quiero cambiar “python” por “python2”. Y resulta que pasa algo bien raro cuando encuentra un “-“. Resulta que de un conjunto de datos le puse a cambiar el nombre y oh sorpresa al intentar ejecutar lo que quería ejecutar me encuentro con que la palabra “python” que había pedido reemplazar únicamente cuando estuviese completa y no entre texto (con \b). Había reemplazado “-lpython” por “-lpython2”.
    Así que te pido ayuda de como evitar que esto suceda ya que hasta el momento me ha tocado usar un parche provisional que revierte el proceso en los ficheros afectados. Gracias.

    • Eso es porque considera que la palabra comienza justo detrás del guión.

      Prueba con la siguiente combinación

      OLD="python"; NEW="python2"; sed -i -e "s/[ ]${OLD}\b/ ${NEW}/g" `grep -lir "$OLD\b" /tmp/kk`

      y nos cuentas.

      Si necesitas ayuda con el cambio no dudes en preguntar por qué lo he reescrito de este modo

      Suerte y un saludo

      • helq dijo:

        gracias por responder @Informático de Guardia (valla que largo nick), funciona, pero no del todo ya que no necesito que ignore todas las palabras “python” que no tengan un espacio detrás de ellas, por ejemplo necesito que reemplace la sentencia ‘python -c “__import__(str(%d))”‘ (con las comillas) pero no lo hace porque no lo antecede un espacio sino una comilla.

        PD1: Para darme a entender más, el script que cree con la sentencia que te específiqué es el PKGBUILD que está aquí: http://aur.archlinux.org/packages.php?ID=49412
        PD2: Aún así, no te gustaría explicarnos que es lo que hace específicamente el “[ ]”? y si es lo mismo que ” “?.
        Gracias de nuevo 😀

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s