Página 1 de 1

Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-14 15:51 @702
por enric73
Hola, tengo una consulta: Cómo puedo modificar a la vez una palabra por otra en el nombre de unos ficheros y en su contenido.
El nombre de los ficheros tiene un patrón común, plujatempabril.htm, todos empiezan por el nombre de una población. Por ejemplo, Barcelonaplujatempabril.htm, Valenciaplujatempabril.htm... Quiero cambiar abril por mayo... en el nombre de los ficheros y en el interior de los ficheros. En el siguiente código realizo el cambio para un fichero en concreto, pero para todos ¿cómo debo hacerlo? Gracias.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. chdir "$ENV{HOME}/htm/prova";
  2.  
  3. #open(LS, "ls *plujatempabril.htm") or die $!;
  4. #while (<*plujatempabril.>){
  5. my $archivo = 'olotplujatempabril';
  6. open my $INFILE, '<', "$archivo.htm";
  7. my @archivo = <$INFILE>;
  8. foreach (@archivo) {
  9.     s/abril/mayo/g;
  10.     s/Abril/Mayo/g;
  11. }
  12.  
  13. #chomp $archivo[-1];
  14. close $INFILE;
  15. open my $OUTFILE, '>', "olotplujatempmayo.htm";
  16. print $OUTFILE @archivo;
  17. close $OUTFILE;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Gracias otra vez.

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-14 17:23 @766
por explorer
Bueno, son dos procesos distintos: el interior y el nombre del archivo.

Yo leería el contenido, haría el cambio en el interior, y luego grabaría el resultado en el nuevo archivo (así, el archivo anterior no lo pierdo).
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use autodie;
  2.  
  3. my $patro     = 'plujatempabril.htm';
  4. my $patro_nou = 'plujatempmayo.htm';
  5.  
  6. chdir "$ENV{HOME}/htm/prova";
  7.  
  8. while (my $arxiu = <*$patro>) {                 # mientras existan archivos coincidentes con el patrón
  9.  
  10.     my($ciutat) = $arxiu =~ /^(\w+)$patro/;     # extracción del nombre de la ciudad: es lo que hay delante del patrón
  11.  
  12.     open my $INFILE, '<', $arxiu;               # abrimos
  13.     open my $OUTFILE,'>', "$ciutat$patro_nou";
  14.  
  15.     while(<$INFILE>) {                          # leemos
  16.         s/abril/mayo/g;                         # cambiamos
  17.         s/Abril/Mayo/g;
  18.  
  19.         print $OUTFILE $_;                      # escribimos
  20.     }
  21.     close $INFILE;                              # y nos vamos
  22.     close $OUTFILE;
  23. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-15 10:45 @489
por enric73
Gracias, explorer.

Entiendo el código, pero solamente me crea un fichero plujatempmayo.htm y dentro está el contenido de la última población y con las palabras mayo y Mayo. No reconoce $ciutat...

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-15 11:44 @530
por explorer
Ya está arreglado. Hay que cambiar $archivo por $arxiu en la línea 10.

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-16 04:17 @220
por enric73
Gracias, explorer.

Hay una línea que no entiendo, en concreto esta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my($ciutat) = $arxiu =~ /^(\w+)$patro/;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

$arxiu es el nombre completo del archivo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $arxiu = <*$patro>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
pero en la línea 10, lo igualamos a my($ciutat), no llego a entenderlo.

Saludos.

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-16 07:36 @358
por explorer
En la línea 8, con la ayuda del operador diamante, vamos obteniendo un nombre de archivo completo, en cada vuelta del while().

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. while (my $arxiu = <*$patro>) {
  2.  
  3.     my($ciutat) = $arxiu =~ /^(\w+)$patro/;
  4.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

En la línea 8, se recorre cada nombre de archivo que coincida con el patrón. $arxiu va tomando cada nombre de archivo.

Por ejemplo, en una vuelta sería $arxiu igual a 'Barcelonaplujatempabril.htm'.

A continuación viene la línea 10. En ella, aplicamos la expresión regular a $arxiu. La expresión regular lo que hace es:
  • busca desde el comienzo de la cadena de caracteres (^)
  • seguido por uno o más (+) caracteres alfanuméricos (\w)
  • esos caracteres serán capturados (())
  • y deben ser seguidos por el patrón $patro
Si el nombre del archivo coincide con todo este patrón, tendremos capturado en $1 el comienzo del nombre del archivo. En nuestro ejemplo, 'Barcelona'.

Luego, Perl mira a la izquierda. Y lo que se encuentra es un par de paréntesis: my($ciutat). Entonces, el comportamiento de la expresión regular cambia, porque Perl se da cuenta de que se está ejecutando en contexto de lista, no en contexto de escalar.

Si hubiéramos escrito my $ciutat = $arxiu =~ /^(\w+)$patro/; (sin los paréntesis), estaríamos ejecutándolo en contexto escalar, y el resultado que se almacena en $ciutat sería un valor de verdad '1' (verdadero) o '' (cadena nula, falso), para indicar si la expresión regular ha conseguido una coincidencia entre $arxiu y el patrón.

Pero... al poner los paréntesis a la izquierda, estamos queriendo decir que queremos que se ejecute en contexto de lista, y la consecuencia de ello es que la exp. reg. devuelve una lista de valores, que serán las capturas hechas dentro del patrón.

En el patrón solo tenemos un par de paréntesis de captura, así que la exp. reg. devuelve una lista de valores de un solo valor ('Barcelona'). Y se almacena en las variables que están entre los paréntesis de la izquierda.

Así que 'Barcelona' se almacena en $ciutat, que usaremos luego en la línea 13 para crear el nuevo nombre de archivo.

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-17 14:01 @625
por enric73
Muchas gracias, explorer, por esta explicación tan desarrollada. Saludos.

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-17 16:17 @720
por enric73
Una última pregunta sobre este asunto... si quisiera mantener el mismo nombre de fichero, que el nombre del $OUTPUT sea igual al $INPUT, ¿cómo se procede? He estado modificando '<', pero el fichero que me guarda está vacío.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. open my $INFILE, '<', $arxiu;               # abrimos
  2. open my $OUTFILE,'>', "$ciutat$patro_nou";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Re: Modificar diversos ficheros a la vez en un directorio

NotaPublicado: 2014-04-17 16:39 @735
por explorer
Lo que puedes hacer es que la salida vaya a un archivo con un nombre temporal, y cuando hayas terminado de sacar todas las filas, haces un move() desde el nombre temporal al definitivo. El move() lo encuentras en el módulo File::Copy.