2010-05-26 6 views
6

Por alguna razón Perl mantiene almacenamiento en caché de las entradas de directorio que estoy tratando de leer usando readdir:¿Por qué las entradas de directorio de caché readdir() de Perl?

opendir(SNIPPETS, $dir_snippets); # or die... 
while (my $snippet = readdir(SNIPPETS)) 
{ print ">>>".$snippet."\n"; } 
closedir(SNIPPETS); 

Desde mi directorio contiene dos archivos, test.pl y test.man, estoy esperando el siguiente resultado:

. 
.. 
test.pl 
test.man 

Desafortunadamente Perl devuelve una gran cantidad de archivos que ya han desaparecido, por ejemplo, porque traté de cambiar el nombre de ellos. Después me muevo test.pl a test.yeah Perl devolverá la lista siguiente:

. 
.. 
test.pl 
test.yeah 
test.man 

¿Cuál es la razón de este comportamiento extraño? La documentación para opendir, readdir y closedir no menciona algún tipo de mecanismo de caché. "ls -l" enumera claramente solo dos archivos.

+0

Tanto '' readline' y readdir' prelectura y caché. Es la naturaleza de la bestia. – tchrist

Respuesta

9

El resultado de opendir parece ser una lista de archivos que estaban en el directorio en el momento en que se llamó. Si se altera el directorio necesita llamar rewinddir:

my $dir_snippets = "/tmp/fruit"; 
system ("rm -rf $dir_snippets"); 
mkdir $dir_snippets or die $!; 
my $banana = "$dir_snippets/banana"; 
system ("touch $banana"); 
opendir(SNIPPETS, $dir_snippets); # or die... 
while (my $snippet = readdir(SNIPPETS)) { 
    if (-f $banana) { 
     unlink $banana; 
     rewinddir SNIPPETS; 
    } 
    print ">>>".$snippet."\n"; 
} 
closedir(SNIPPETS); 

Le da

 
>>>. 
>>>. 
>>>.. 

Sin la rewinddir se obtiene

 
>>>. 
>>>.. 
>>>banana 

haciendo una prueba con C, tengo la misma cosa:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <dirent.h> 
#include <errno.h> 

int main() 
{ 
    DIR * fruit; 
    struct dirent * file; 

    fruit = opendir ("/tmp/fruit"); 
    if (! fruit) { 
     fprintf (stderr, "opendir failed: %s\n", strerror (errno)); 
     exit (EXIT_FAILURE); 
    } 
    while (file = readdir (fruit)) { 
     unlink ("/tmp/fruit/banana"); 
     printf (">>> %s\n", file->d_name); 
    } 
    closedir (fruit); 
} 

dicta la siguiente (después de crear el "banana" archivo con "toque"):

 
$ ./a.out 
>>> . 
>>> .. 
>>> banana 
$ ./a.out 
>>> . 
>>> .. 
+0

Whoa, funciona como encanto ahora, gracias! Llamé a opendir() directamente sobre el guión esperando que readdir() hiciera la lectura real, bueno. tl; dr: Llama call opendir justo antes de readdir o usa rewinddir si esperas cambios en el directorio desde el que estás leyendo. –

Cuestiones relacionadas