Почему Perl readdir () кэширует записи каталога? - PullRequest
6 голосов
/ 26 мая 2010

По какой-то причине Perl продолжает кэшировать записи каталога, которые я пытаюсь прочитать, используя readdir :

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

Поскольку мой каталог содержит два файла: test.pl и test.man , я ожидаю следующий вывод:

.
..
test.pl
test.man

К сожалению, Perl возвращает много файлов, которые с тех пор исчезли, например, потому что я пытался переименовать их. После перемещения test.pl в test.yeah Perl вернет следующий список:

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

В чем причина этого странного поведения? В документации для opendir , readdir и closedir не упоминается какой-либо механизм кэширования. "ls -l" содержит только два файла.

1 Ответ

9 голосов
/ 26 мая 2010

Результат opendir представляется списком файлов, которые были в каталоге на момент его вызова. Если вы измените каталог, вам нужно позвонить 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);

Дает вам

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

Без перемотки вы получаете

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

Просто тестируя с C, я получаю то же самое:

#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);
}

Дает следующее (после создания файла «банан» с «прикосновением»):

$ ./a.out 
>>> .
>>> ..
>>> banana
$ ./a.out 
>>> .
>>> ..
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...