2013-05-28 13 views
5

Esiste un modo per garantire un ordine dall'elenco restituito da readdir?Perl readdir nell'ordine

Ho il codice:

opendir(my $DIR, $src) or die "Error opening $src"; 

# Loop for each file in the directory 
while (my $file = readdir($DIR)) 
{ 
     print "$file\n"; 
} 

ma restituisce in ordine casuale. Ora so che ci sono molte soluzioni tramite una rapida ricerca su Google, ma non riesco a trovare l'ordine esatto di cui ho bisogno .. Fondamentalmente voglio che le cartelle appaiano PRIMA o ULTIMA, e non tra i file.

Per esempio, in questo momento se ho la struttura di cartelle:

folder 
folder 
file1 
file2 
file3 

ottengo il risultato:

file2 
folder 
folder 
file1 
file3 

quando in realtà voglio:

folder 
folder 
file1 
file2 
file3 

Oppure:

file1 
file2 
file3 
folder 
folder 

Un modo per raggiungere questo obiettivo?

Grazie.

+0

deve essere usato un qualche tipo di sorta. –

risposta

4

È possibile ordinare mettendo le cartelle prima e poi l'ordinamento per file/dir name,

# $src pointing to folder open with opendir 
my @sorted_dir = 
    map $_->[0], 
    sort { 
    $a->[1] <=> $b->[1] 
     || 
    $a->[0] cmp $b->[0] 
    } 
    map [ $_, -f "$src/$_" ], 
    readdir($DIR); 

Mentre effetto simile può essere ottenuto con,

for my $file (sort { -f "$src/$a" <=> -f "$src/$b" } readdir($DIR)) { 
    print "$file\n"; 
} 

è più lento e inefficiente, come più spesso va al file system controllando se la voce della directory è un file semplice.

+0

Grazie, speravo comunque in una soluzione più elegante. Ritornerò su questo se tutto il resto fallisce :) – Travv92

+0

Aggiornato con un'alternativa più semplice ma più lenta. –

+0

Grazie, è più bello. Questo era anche il problema con l'altra soluzione fornita da simbabque, mancava '$ src /' ed è per questo che non funzionava! – Travv92

5

È possibile utilizzare uno sort per farlo, esaminando ogni voce della lista restituita da readdir.

opendir(my $DIR, '.') or die "Error opening "; 

foreach my $file (sort { -d $a <=> -d $b } readdir($DIR)) { 
    print "$file\n"; 
} 

Questo darà le cartelle per ultime.

+0

Salve, quando lo faccio ottengo 'Uso del valore non inizializzato nel confronto numerico (<=>)'. – Travv92

+0

Prova 'cmp' invece di' <=> '. – innaM

+0

Ora viene visualizzato "Uso del valore non inizializzato nel confronto tra stringhe (cmp)". La rimozione di '-d' da entrambi non produce errori (ma ovviamente output errato) .. – Travv92

2

È possibile utilizzare part da List::MoreUtils

#!/usr/bin/env perl 

use strict; 
use warnings; 

use List::MoreUtils 'part'; 

my $dir = shift || '.'; 

opendir my $dh, $dir or die "Cannot open $dir"; 

my ($files, $dirs) = part { -d } sort readdir $dh; 

print "$_\n" for @$files, @$dirs; 

Per un'altra idea, si potrebbe guardare File::Next.

+0

Grazie, anche se preferisco farlo senza pacchetti .. – Travv92

+0

Funziona, è facile da leggere e quasi sicuramente ce l'hai già. Ma ... la tua scelta. –

3

foreach (sort readdir $dh) {} funziona bene per me.

Ad esempio:

opendir (my $DIR, "$dir") || die "Error while opening $dir: $!\n"; 

foreach my $dirFileName(sort readdir $DIR) 
{ 
     next if $dirFileName eq '.' or $dirFileName eq '..'; 
     print("fileName: $dirFileName ... \n"); 
}