2009-01-12 7 views
8

Lorsque je lis un répertoire en Perl avec opendir, readdir et closedir, la fonction readdir ne semble pas lire les fichiers dans un ordre spécifique (que je peux dire).Comment puis-je lire les fichiers dans un répertoire dans l'ordre de tri?

Je lis un répertoire qui a des sous-répertoires nommés par timestamp:

1224161460 
1228324260 
1229698140 

Je veux lire dans ces répertoires dans l'ordre numérique, ce qui placerait les répertoires les plus anciens d'abord.

Lorsque j'utilise readdir, le premier qu'il lit est 1228324260, qui est le milieu. Je sais que je pourrais mettre le contenu du répertoire dans un tableau et trier le tableau, mais y at-il une option que je peux passer à readdir pour lire dans l'ordre trié? Ou peut-être un moyen plus élégant d'accomplir cela que de tout pousser dans le tableau et de trier le tableau? Il existe probablement des modules pour cela, mais il est difficile d'installer des modules dans notre environnement, donc à moins qu'il ne s'agisse d'un module intégré je préférerais ne pas utiliser de modules ...

Merci!

EDIT Comme l'a demandé, je posterai le code que j'utilise:

opendir(my $data_dh, $data_dir) or die "Cannot open $data_dir\n"; 
while (my $name = readdir($data_dh)) { 
    next if ($name eq '.' or $name eq '..'); 
    my $full_path = "${data_dir}/${name}"; 
    next unless (-d $full_path); 
    process_dir($full_path); 
} 
closedir($data_dh); 
+0

J'utilise Perl 5.8.2 sur une zone AIX, si cela fait une différence – BrianH

+0

je sais que c'est un script simple, mais pouvez-vous envoyer votre code afin que nous ne devons pas le reproduire? –

+1

Le signe & avant process_dir n'est pas nécessaire et peut dans certains cas être dangereux. Je vous conseille de l'enlever. –

Répondre

13

readdir peut être appelée dans un contexte de tableau, donc faire ceci:

opendir(my $data_dh, $data_dir) or die "Cannot open $data_dir\n"; 
my @files = sort { $a <=> $b } readdir($data_dh); 
while (my $name = shift @files) { 
... 
+0

Vous n'avez pas besoin du bloc {$ a <=> $ b}, la valeur par défaut est ici – Svante

+2

NO, la valeur par défaut La valeur par défaut est trie lexicalement, et non numériquement.Les horodatages précédant 2001-09-09T01: 46: 40 seraient triés plus tard que la plupart des horodatages après, car ils ont franchi la barre des 1 000 000 000 de secondes. –

+0

Vraiment cependant, opendir est exagéré ici. Votre meilleur pari serait d'utiliser glob() ... pas de poignées de répertoire à s'inquiéter. –

5

Vous pouvez l'essayer avec un peu de magie Glob, glob semble fonctionner de manière triée, donc ceci:

# Glob in scalar context iterates the result set internally 
while(defined(my $dir = glob($dir . '/*'))){ 
    print $dir, "\n"; 
    # $dir is fed ordered and with full names. 
} 

ou

# Glob in list context returns all results. 
for(glob($dir.'/*')){ 
    print $dir , "\n"; 
    # also ordered. 
} 

devrait fonctionner. Il suffit de faire attention à glob, parce que cela:

for(0..20){ 
    printf "%30s|%30s\n", glob($dir.'/*'), glob($dir.'/*'); 
} 

fait quelque chose semi-magique, et imprime le contenu dir deux fois sur chaque ligne. à savoir:

/foo/bar/a | /foo/bar/a 
/foo/bar/b | /foo/bar/b 
/foo/bar/c | /foo/bar/c 
/foo/bar/d | /foo/bar/d 
+1

C'est probablement la meilleure façon de le faire. opendir est vraiment exagéré ici. –

5

Il suffit de jeter un sort devant un opérateur de liste que vous souhaitez réorganiser. Vous n'avez pas non plus besoin de stocker les résultats dans un tableau. Vous pouvez utiliser un foreach:

opendir my($dh), $dirname or die "Could not open directory [$dirname]: $!"; 

foreach my $file (sort { $a <=> $b } readdir $dh) 
    { 
    ... 
    } 
+0

++ pour simplifier, mais je pense que quelqu'un a cassé votre code de balisage (le bloc de tri). – converter42

+0

Ah, ouais, les pré-blocs n'aiment pas les chevrons, même si ça ressort bien dans l'aperçu. –

Questions connexes