Сортировка имен каталогов с помощью Perl - PullRequest
2 голосов
/ 26 февраля 2011

Я хочу отсортировать / распечатать файлы в каталоге по имени. Мой код перечисляет их все, но сортировка перекошена. Вот мой код и результаты. Любые предложения будут приветствоваться!

my $file;
opendir (DIR, "$dir");
while ($file = readdir(DIR)) {
    push (my @files, $file);
    @files = sort {$a cmp $b} @files;   #NOT sorting!
    foreach $file (@files) {
        print "$file\n";
    }
}

А вот "отсортированные" результаты:

Screenshot-Chess_-_Human_versus_GNUchess.png  
test.html  
katyperry.gif  
test.cgi  
Californication.S04E05.HDTV.XviD-ASAP.avi  
FreeWatch_13.exe  
proxy.jpg  
test.pl-  
.  
attachment2.jpg  
attachment.jpg  
Californication.S04E06.HDTV.XviD-LOL.avi  
Californication.S04E07.HDTV.XviD-LOL.avi  
boxter.jpg  
..  

Ответы [ 7 ]

11 голосов
/ 26 февраля 2011

Вы создаете серию одноэлементных списков, сортируете каждый (который не предназначен) и распечатываете его.То, что вы хотите сделать, это прочитать весь список файлов в один список, а затем отсортировать его следующим образом:

my $file;
my @files;
opendir (DIR, "$dir");
while ($file = readdir(DIR)) {
    push (@files, $file);
}
@files = sort {$a cmp $b} @files;
foreach $file (@files) {
    print "$file\n";
}
5 голосов
/ 26 февраля 2011

Другой способ, используя File :: Slurp

use warnings; 
use strict; 
use File::Slurp;
use Data::Dumper;

my @files = read_dir($dir);
@files = sort @files;
print Dumper(\@files);

Это заботится об открытии и закрытии каталога, проверке на успешность, и автоматически исключая спец. и .. каталоги, которые вы, вероятно, не хочу.

3 голосов
/ 26 февраля 2011

my @files в лексической области видимости цикла while всегда приведет к созданию нового массива @files на каждой итерации цикла. Следовательно, в любое время @files будет содержать только один элемент, и сортировка, таким образом, не имеет смысла. Теперь посмотрите ответ Аноми .

2 голосов
/ 26 февраля 2011

Серьезно, вы делаете гораздо больше работы, чем должны.

use warnings;
use strict;
use autodie;
use File::Spec::Functions qw'no_upwards';

my $dir = '.';

opendir my($dh), $dir;
for my $file ( no_upwards sort readdir $dh ){
  print "$file\n";
}
closedir $dh;
1 голос
/ 22 октября 2013

Сортировка путей сложна, потому что в последовательности сортировки ASCII разделитель пути, косая черта (/) стоит перед большинством символов пути, но не перед всеми, в особенности точка и тире.

Разбейте пути на элементы пути, разделив их на косую черту. Сравнивайте элементы пути в алфавитном порядке с cmp. Если это связь, то путь с меньшим количеством элементов предшествует пути с большим количеством элементов.

Обязательно отрубите все новые строки. Используйте подпрограмму & bypath с командой Perl sort: sort bypath @files;

sub bypath {
  my @a = split m'/', $a;
  my @b = split m'/', $b;
  for ( my $i = 0; $i<=$#a; $i++ ) {
    last if $i > $#b;
    return $a[$i] cmp $b[$i] if $a[$i] cmp $b[$i];
    }
  return $#a <=> $#b;
  }

Пример результатов:

  • это
  • это / что
  • это / что / другое
  • это / что / другое / FILEA
  • это / что / другое / FILEB
  • это / что / other.new / FILEA
0 голосов
/ 01 апреля 2017

Я не понимаю, почему вы, ребята, делаете это так сложно.Это прекрасно работает для сортировки файлов или папок.

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");
}
0 голосов
/ 22 октября 2013
use v5.10;
say for sort do { opendir( my $fh, $dir ); readdir($fh) };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...