2010-05-26 16 views
6

Per qualche motivo Perl mantiene la memorizzazione nella cache le voci di directory che sto cercando di leggere con readdir:Perché le voci della directory della cache readdir() di Perl?

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

Dal momento che la mia directory contiene due file, test.pl e test.man, mi aspetto il seguente output:

. 
.. 
test.pl 
test.man 

Purtroppo Perl restituisce un sacco di file che da allora sono scomparsi, per esempio perché ho cercato di rinominarli. Dopo mi muovo test.pl-test.yeah Perl restituirà il seguente elenco:

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

Qual è il motivo di questo strano comportamento? La documentazione per opendir, readdir e closedir non menziona alcun tipo di meccanismo di memorizzazione nella cache. "ls -l" elenca chiaramente solo due file.

+0

Sia 'readline' che' readdir' pre-read e cache. È la natura della bestia. – tchrist

risposta

9

Il risultato di opendir sembra essere un elenco di file presenti nella directory al momento della chiamata. Se si modifica la directory è necessario chiamare 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); 

Ti dà

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

Senza il rewinddir si ottiene

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

solo test con C, ottengo la stessa 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); 
} 

Fornisce quanto segue (dopo aver creato il file "banana" con "touch"):

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

Whoa, funziona come un incantesimo ora, grazie! Ho chiamato opendir() proprio sopra lo script aspettando readdir() per fare la lettura vera e propria. tl; dr: O chiamate opendir prima di readdir o usa rewinddir se ti aspetti cambiamenti nella directory da cui stai leggendo. –

Problemi correlati