2013-05-28 14 views
5

Czy istnieje sposób na zagwarantowanie zamówienia z listy zwróconej przez readdir?Perl readdir w celu

mam kod:

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

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

Ale powraca w kolejności losowej. Teraz wiem, że istnieje wiele rozwiązań za pomocą szybkiego wyszukiwania w Google, ale nie mogę znaleźć dokładnej kolejności potrzebnej. Zasadniczo chcę, aby foldery pojawiały się FIRST lub LAST, a nie pomiędzy plikami.

Na przykład teraz, czy mam strukturę folderu:

folder 
folder 
file1 
file2 
file3 

uzyskać wynik:

file2 
folder 
folder 
file1 
file3 

Kiedy naprawdę chcę:

folder 
folder 
file1 
file2 
file3 

czyli

file1 
file2 
file3 
folder 
folder 

Jakikolwiek sposób to osiągnąć?

Dzięki.

+0

jakimś rodzaju powinny być stosowane. –

Odpowiedz

4

można sortować poprzez umieszczenie foldery, a następnie sortując pliku/dir nazwie

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

Choć podobny efekt można osiągnąć,

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

to wolniej i nieefektywne jak to częściej przechodzi do sprawdzania systemu plików, jeśli wpis w katalogu jest zwykłym plikiem.

+0

Dzięki, miałem nadzieję na bardziej eleganckie rozwiązanie. Powrócę do tego, jeśli wszystko inne zawiedzie :) – Travv92

+0

Zaktualizowany prostszą, ale wolniejszą alternatywą. –

+0

Dzięki, to ładniej wygląda. To był również problem z innym rozwiązaniem dostarczonym przez simbabque, brakowało '$ src /' i dlatego to nie działało! – Travv92

5

Możesz użyć do tego celu sort, patrząc na każdy wpis na liście zwróconej przez readdir.

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

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

Da to foldery jako ostatnie.

+0

Witam, kiedy to zrobię, otrzymuję komunikat "Używanie niezainicjowanej wartości w porównaniu numerycznym (<=>)". – Travv92

+0

Wypróbuj 'cmp' zamiast' <=> '. – innaM

+0

Teraz otrzymuję komunikat "Użycie niezainicjowanej wartości w porównywaniu ciągów (cmp)". Usunięcie '-d' z obu nie powoduje błędów (ale oczywiście błędne wyjście) .. – Travv92

2

Można użyć part z 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; 

Dla innego pomysłu, można spojrzeć na File::Next.

+0

Dzięki, choć wolę to robić bez pakietów .. – Travv92

+0

Działa, jest łatwy do odczytania, a już prawie na pewno go już masz. Ale ... twój wybór. –

3

foreach (sort readdir $dh) {} działa dobrze dla mnie.

Na przykład:

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