Buscar y reemplazar texto en muchos ficheros

El otro día tenía la necesidad de buscar y reemplazar de forma masiva y automática un texto (html) en muchos ficheros a la vez, y hacerlo a mano era una locura. Con este script en perl que encontré en Internet (también pregunte en Twitter y me ayudaron mucho) podemos buscar y sustituir texto de forma recursiva. La primera utilidad de un código así es ante un problema de seguridad en el que nos inyecten código en nuestras páginas podremos detectar el código y sustituirlo de forma rápida.

#!/usr/bin/perl
# A simple recursive find and replace tool
# Copyright (C) 2010 Anatoliy Dimitrov, website-security.info

#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#If used escape these characters . * ? + [ ] ( ) { } ^ $ | \ ;
#The ‘s’ RE modifier makes it work on more than one line by default.

use strict;
use warnings;
use File::Find;
use Cwd;

my $changefrom = ‘code to be replaced\n’; #always leave \n at the end to avoid blank lines being left
my $changeto = ; #usually empty unless you want to place something
my $extensions = ‘.php’;
my $path = cwd; #usually the current working directory

#do not change anything below this line

sub matchPattern {

my $file = $File::Find::name;

if ($file =~ /$extensions/) {
open INPUT, ‘<‘, $file or warn;
my @input_array=<INPUT>;
close(INPUT);
my $file_code=join(“”,@input_array);
$file_code =~ s#$changefrom#$changeto#sg;
open OUTPUT, ‘>’, $file or warn;
print(OUTPUT $file_code);
close(OUTPUT);
}

}

find (\&matchPattern, $path);

En este script tenemos que destacar las variables del principio que son las que nos ayudarán en nuestra tareas:

  • $changefrom es el texto que vamos a buscar para sustituir por el que pondremos en $changeto
  • $extensions es la extensión de fichero en las que se buscarán las cadenas a sustituir.

Por poner un ejemplo por si nos han inyectado código malicioso en nuestros ficheros php, imaginar que nos ha introducido esto:

<script type=”text/javascript”>
alert(“¿Estas seguro de que tu sitio web está protegido?”)
</script>
En este caso en el $changefrom no hace falta ponerlo todo por si el patrón cambia, podéis introducirlo así:
my $changefrom ='<script.*seguro.*cript>\n’;

Vamos que podéis usar expresiones regulares sin problemas para las buscar y sustituir. Si necesitais un retorno de carro para añadir o eliminar recordar que podéis usar \n.

El código original lo podéis conseguir en GitHub. vía: Website-security

  • Una forma algo más rápida, desde shell:

    find directorio/ -type f -iname “*.html” -exec perl -pi.bak -e ‘s/texto_viejo/texto_nuevo/g’ {} \;

    ;-)

  • Paco Ros

    El programa rpl (aptitude install rpl en sistemas basados en Debian) disponible para todas las plataformas hace precisamente eso :-)