2013-05-28 26 views
5

Có cách nào để đảm bảo đơn đặt hàng từ danh sách được trả về bởi readdir không?Perl readdir theo thứ tự

Tôi có đoạn code:

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

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

Nhưng nó sẽ trả về theo thứ tự ngẫu nhiên. Bây giờ tôi biết có rất nhiều giải pháp thông qua tìm kiếm nhanh trên Google, nhưng tôi không thể tìm thấy thứ tự chính xác tôi cần .. Về cơ bản, tôi muốn các thư mục xuất hiện FIRST hoặc LAST và không nằm giữa các tệp.

Ví dụ, ngay bây giờ nếu tôi có cấu trúc thư mục:

folder 
folder 
file1 
file2 
file3 

tôi nhận được kết quả:

file2 
folder 
folder 
file1 
file3 

Khi thực sự tôi muốn:

folder 
folder 
file1 
file2 
file3 

Hoặc:

file1 
file2 
file3 
folder 
folder 

Bất kỳ cách nào để đạt được điều này?

Cảm ơn.

+0

một số loại loại nên được sử dụng. –

Trả lời

4

Bạn có thể sắp xếp bằng cách đặt các thư mục đầu tiên và sau đó sắp xếp theo tập tin/tên dir,

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

Trong khi hiệu ứng tương tự có thể đạt được với,

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

nó chậm và không hiệu quả vì nó thường xuyên hơn đi đến kiểm tra hệ thống tập tin nếu mục nhập thư mục là một tập tin đơn giản.

+0

Cảm ơn, tôi đã hy vọng cho một giải pháp thanh lịch hơn mặc dù. Tôi sẽ rơi trở lại này nếu tất cả những người khác không :) – Travv92

+0

Cập nhật với sự thay thế đơn giản nhưng chậm hơn. –

+0

Cảm ơn, đó là một cái nhìn đẹp hơn. Đó cũng là vấn đề với giải pháp khác do simbabque cung cấp, nó thiếu '$ src /' và đó là lý do tại sao nó không hoạt động! – Travv92

5

Bạn có thể sử dụng sort để thực hiện việc này, bằng cách xem từng mục nhập của danh sách được trả về readdir.

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

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

Điều này sẽ cung cấp cho các thư mục cuối cùng.

+0

Xin chào, khi tôi thực hiện việc này, tôi nhận được 'Sử dụng giá trị chưa được khởi tạo trong so sánh số (<=>)'. – Travv92

+0

Thử 'cmp' thay vì' <=> '. – innaM

+0

Bây giờ tôi nhận được 'Sử dụng giá trị uninitialized trong so sánh chuỗi (cmp)'. Loại bỏ các '-d' từ cả hai sản lượng không có lỗi (nhưng rõ ràng là sai đầu ra) .. – Travv92

2

Bạn có thể sử dụng part từ 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; 

Đối với ý tưởng khác, bạn có thể nhìn vào File::Next.

+0

Cảm ơn, mặc dù tôi thích làm điều này mà không cần gói. – Travv92

+0

Nó hoạt động, dễ đọc và bạn gần như chắc chắn đã có nó. Nhưng ... sự lựa chọn của bạn. –

3

foreach (sort readdir $dh) {} hoạt động tốt cho tôi.

Ví dụ:

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