• Publicidad

Función recursiva para listar contenido de un directorio

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Función recursiva para listar contenido de un directorio

Notapor Alex0520 » 2009-11-09 09:06 @421

Hola, soy nuevo en este foro...

Estoy tratando de hacer una función recursiva en Perl que lista el contenido de un directorio, y comprueba si cada elemento es un archivo; si lo es, lo que hace es aplicarle una expresión regular; si por el contrario es un directorio, lo que debe hacer es volverse a aplicar dentro del directorio... Gracias...

Aquí está el código
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!C:/Perl64/bin/perl.exe -w
  2. sub buscarxtitulo($$) {
  3.     my $directorio = $_[0];
  4.     my $parametro  = $_[1];
  5.  
  6.     opendir(DIR,$directorio);
  7.     @archivos = readdir(DIR);
  8.     close(DIR);
  9.  
  10.     foreach $archivo (@archivos) {
  11.         next if $archivo eq "." || $archivo eq "..";
  12.  
  13.         if (-f $archivo) {
  14.             if ($archivo =~ /$parametro/io) {
  15.                 print $archivo;
  16.             }
  17.         }
  18.         elsif (-d $archivo) {
  19.             buscarxtitulo($archivo,$parametro);
  20.         }
  21.     }
  22. }
  23.  
  24. open(D,"Datos.txt");
  25.  
  26. $directorio = <D>;
  27. $parametro  = <D>;
  28. $tipo       = <D>;
  29.  
  30. chomp($directorio);
  31. chomp($parametro);
  32. chomp($tipo);
  33.  
  34. print $directorio."\n";
  35. print $parametro."\n";
  36. print $tipo."\n";
  37.  
  38. if ($tipo eq "Titulo") {
  39.     buscarxtitulo($directorio,$parametro);
  40. }
  41.  
  42. close(D);
  43.  
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2009-11-09 09:43 @446, editado 2 veces en total
Razón: Formateo, bloques de código, ortografía, sintaxis
Alex0520
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2009-11-09 08:49 @409

Publicidad

Re: Funcion recursiva...

Notapor Jenda » 2009-11-09 09:29 @436

Alex0520 escribiste:Estoy tratando de hacer una función recursiva en Perl que lista el contenido de un directorio, y comprueba si cada elemento es un archivo; si lo es, lo que hace es aplicarle una expresión regular; si por el contrario es un directorio, lo que debe hacer es volverse a aplicar dentro del directorio... Gracias...


File::Find o File::Find::Rule
-------------------------------------------------------
- Estoy aquí para practicar español. Si te ayudó mi respuesta ayudame con un mensaje privado sobre mis faltas por favor. Seguramente habrá muchas :-)
Jenda
Perlero nuevo
Perlero nuevo
 
Mensajes: 132
Registrado: 2007-10-29 06:31 @313
Ubicación: Praga, Republica Checa

Re: Función recursiva para listar contenido de un directorio

Notapor Alex0520 » 2009-11-09 11:15 @510

mmm. No puedo hacerlo con lo que tu propones, ya que los parámetros del trabajo, me obligan a hacerlo así...
Alex0520
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2009-11-09 08:49 @409

Re: Función recursiva para listar contenido de un directorio

Notapor explorer » 2009-11-09 11:50 @534

Bienvenido a los foros de Perl en Español, Alex0520.

Como dice Jenda, una opción es estudiar el código de los módulos File::. O usarlos directamente.

En cuanto al código tuyo, hay una serie de problemas...

Al tratarse de una función recursiva, no debes permitir que las variables que almacenan información en un estado o contexto, pasen a la siguiente llamada de la función.

En tu código, estás usando la variable @archivos para guardar los archivos que hay en cada directorio en que entras. Luego inicias un bucle por todos ellos. Si son ficheros normales haces la prueba de la exp. reg., pero si son directorios, vuelves a llamar a la función. Y aquí está el primer fallo: cuando entra la función a analizar el contenido de ese directorio, sobreescribe el contenido anterior de @archivos.

La solución es la de siempre: hacer que las variables sean locales en el contexto donde están.

Con poner my @archivos = = readdir(DIR);, vale. De esa manera, se crea una nueva variable @archivos, que es independiente de las siguientes ejecuciones de la subrutina.

Otro detalle es el funcionamiento de opendir(). En la línea 6 le pides que abra el $directorio y que te devuelva luego el contenido del mismo. Hasta ahí, bien. El problema está luego en la línea 19: estás ejecutando la función con el nombre del nuevo directorio encontrado (en la variable $archivo), PERO resulta que este nombre de archivo es RELATIVO a la posición del $directorio abierto por opendir(). Un ejemplo para aclarar las cosas:

Suponemos que estamos en el directorio actual ('.'). Y que el programa lo ejecutamos en este mismo directorio. Como a lo largo del programa y de la subrutina NO realizamos ninguna operación chdir(), NO estamos cambiando de directorio. Seguimos en el primero.

Supongamos que el contenido del directorio es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
.
..
mame/
juegos.txt
README
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Bien, esto es lo que nos devuelve la primera llamada a opendir(). Tenemos 3 directorios y dos ficheros normales. De los directorios '.' y '..' no tenemos que preocuparnos porque les desechamos enseguida. La cuestión es cuando llegamos al primer directorio.

$archivo vale 'mame' y se activa la condición '-d', así que pasamos a la línea 19 del código, donde llamamos a la misma función, pasando como argumento 'mame'. Bueno. Perl llega de nuevo a la línea 6 y, efectivamente, le estamos pidiendo que abra el directorio 'mame' y que nos dé los ficheros que hay dentro. Ahora viene el problema.

Supongamos que ahora, el contenido de 'mame' es el siguiente:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
.
..
roms/
conf/
dir/
mame
mame.txt
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Lo mismo de antes, nos olvidamos de los '.' y '..' y pasamos al primer directorio que se encuentra: 'roms'. Se vuelve a repetir lo de antes: llamamos a la función pasando 'roms' como argumento. Y falla. Falla porque SEGUIMOS estando en el directorio '.' y ahora le estamos pidiendo a opendir() que abra un directorio llamado 'roms'. Y claro: NO HAY ningún directorio así en el lugar donde estamos trabajando. Ese directorio está dentro de otro directorio que sí cuelga del directorio donde estamos.

El problema está claro: opendir() no devuelve el camino completo. Solo devuelve los nombres de los ficheros/directorios del directorio que estamos abriendo, pero sin su ruta completa.

La solución es pasar a la función de llamada el camino completo. Cambiamos la línea 19 por buscarxtitulo("$directorio/$archivo",$parametro);. De esa manera vamos arrastrando en todas las llamadas la ruta completa.

Y por exactamente la misma razón, las líneas 13 y 18 fallarán: estamos preguntando si $archivo es un fichero o un directorio, pero referidos siempre al directorio de trabajo donde estamos. Y eso no es cierto cuando queremos mirar dentro de otros subdirectorios. Hay que cambiar esas líneas para que usen una ruta completa.

Inténtalo ahora.
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Función recursiva para listar contenido de un directorio

Notapor Alex0520 » 2009-11-09 12:31 @563

Hola explorer, gracias por responder, ya hice los cambio que me sugeriste y me quedo asi...
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
1.#!C:/Perl64/bin/perl.exe -w
2.sub buscarxtitulo($$) {
3.    my $directorio = $_[0];
4.    my $parametro  = $_[1];
5.
6.    opendir(DIR,$directorio);
7.    my @archivos = readdir(DIR);
8.    close(DIR);
9.
10.    foreach $archivo (@archivos) {
11.        next if $archivo eq "." || $archivo eq "..";
12.
13.        if (-f $archivo) {
14.            if ($archivo =~ /$parametro/io) {
15.                print $archivo;
16.            }
17.        }
18.        elsif (-d $archivo) {
19.            buscarxtitulo("$directorio\$archivo",$parametro);
20.        }
21.    }
22.}
23.
24.open(D,"Datos.txt");
25.
26.$directorio = <D>;
27.$parametro  = <D>;
28.$tipo       = <D>;
29.
30.chomp($directorio);
31.chomp($parametro);
32.chomp($tipo);
33.
34.print $directorio."\n";
35.print $parametro."\n";
36.print $tipo."\n";
37.
38.if ($tipo eq "Titulo") {
39.    buscarxtitulo($directorio,$parametro);
40.}
41.
42.close(D);
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

en la linea 19, le coloque / porque hago la búsqueda bajo Windows... y al correrlo me aparece
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
buscarxtitulo called too early to check prototype at xxxx\buscador.pl at line 18
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

donde xxxx es la ruta donde está el archivo...
Alex0520
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2009-11-09 08:49 @409

Re: Función recursiva para listar contenido de un directorio

Notapor explorer » 2009-11-09 13:23 @599

En la línea 2, quita

($$)

ya que los prototipos, en Perl, aunque a veces efectivos, dan más problemas que beneficios.

En la línea 19, no debería importar que usaras '/', ya que Perl sabe que está en Windows y haría la conversión. Bueno... de hecho, creo que desde hace años que Windows admite los dos sistemas.

Lo que sí tienes que cambiar es la forma de introducir un '\' en una cadena de caracteres entrecomillada: debes 'escaparlo' al ser un carácter especial.

Quedaría así: buscarxtitulo("$directorio\\$archivo",$parametro);
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Función recursiva para listar contenido de un directorio

Notapor Jenda » 2009-11-09 14:14 @635

Alex0520 escribiste:mmm. No puedo hacerlo con lo que tu propones, ya que los parámetros del trabajo, me obligan a hacerlo así...


¿De qué trabajo? ¿Este código es un deber para un curso? En ese caso sí, pero en todos los demás es mejor usar un módulo. Si no te permiten instalar el módulo en los directorios comunes, instálalo en cualquier otro.

Jenda
-------------------------------------------------------
- Estoy aquí para practicar español. Si te ayudó mi respuesta ayudame con un mensaje privado sobre mis faltas por favor. Seguramente habrá muchas :-)
Jenda
Perlero nuevo
Perlero nuevo
 
Mensajes: 132
Registrado: 2007-10-29 06:31 @313
Ubicación: Praga, Republica Checa

Re: Función recursiva para listar contenido de un directorio

Notapor Alex0520 » 2009-11-09 14:35 @649

Sí, Jenda, esto es un deber para un curso, es por eso que no puedo utilizar lo que tu propones... Muchas gracias.
Alex0520
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2009-11-09 08:49 @409

Re: Función recursiva para listar contenido de un directorio

Notapor explorer » 2009-11-09 14:36 @650

Y las líneas 13 y 18 siguen teniendo el mismo error comentado antes.
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Función recursiva para listar contenido de un directorio

Notapor Alex0520 » 2009-11-09 14:55 @663

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!C:/Perl64/bin/perl.exe -w
  2. sub buscarxtitulo {
  3.     my $directorio = shift;
  4.     my $parametro  = shift;
  5.  
  6.     opendir(DIR,$directorio);
  7.     my @archivos = readdir(DIR);
  8.     close(DIR);
  9.  
  10.     foreach $archivo (@archivos) {
  11.         next if $archivo eq "." || $archivo eq "..";
  12.  
  13.         if (-f $archivo) {
  14.             if ($archivo =~ /$parametro/io) {
  15.                 print $archivo;
  16.             }
  17.         }
  18.         elsif (-d $archivo) {
  19.             buscarxtitulo("$directorio\\$archivo",$parametro);
  20.         }
  21.     }
  22. }
  23.  
  24. open(D,"Datos.txt");
  25.  
  26. $directorio = <D>;
  27. $parametro  = <D>;
  28. $tipo       = <D>;
  29.  
  30. chomp($directorio);
  31. chomp($parametro);
  32. chomp($tipo);
  33.  
  34. print $directorio."\n";
  35. print $parametro."\n";
  36. print $tipo."\n";
  37.  
  38. if ($tipo eq "Titulo") {
  39.     buscarxtitulo($directorio,$parametro);
  40. }
  41.  
  42. close(D);
  43.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Así quedó con las modificaciones que me sugeriste, explorer...

Pero ahora no me muestra nada; cuando lo ejecuto debería mostrarme algún archivo pero no muestra nada... solo muestra los parámetros de búsqueda leídos del archivo, que puse que los imprimiera para ver si los lee...

En el archivo Datos.txt hay
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
C:\Users\Administrator\Documents
bogo
Titulo
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Alex0520
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2009-11-09 08:49 @409

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron