使用Perl对目录文件名进行排序
我想按名称对目录中的文件进行排序/打印。我的代码列出了它们,但是排序是不正确的。这是我的代码和结果。欢迎提出任何建议使用Perl对目录文件名进行排序,perl,sorting,Perl,Sorting,我想按名称对目录中的文件进行排序/打印。我的代码列出了它们,但是排序是不正确的。这是我的代码和结果。欢迎提出任何建议 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 "
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
..
您正在构建一系列单元素列表,对每个列表进行排序(这是一个no-op)并打印它。您要做的是将整个文件列表读取到一个列表中,然后对其进行排序,如下所示:
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";
}
while
循环的词法范围内的my@files
将始终导致在循环的每次迭代中创建一个新的@files
数组。因此,在任何时候,@文件
将只包含一个元素,因此排序毫无意义 另一种方法,使用
这负责打开和关闭目录,检查是否成功,
并自动排除特殊情况。和。。目录,您可能
不想要。说真的,你做的工作比你必须做的多得多
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;
排序路径很棘手,因为在ASCII排序序列中,路径分隔符斜杠(/)在大多数路径字符之前,但不是在所有路径字符之前,最明显的是点和破折号 通过在斜线上拆分,将路径拆分为路径元素。将路径元素与cmp进行字母数字比较。如果是平局,那么元素较少的路径优先于元素较多的路径 一定要咬掉任何新词。结合Perl sort命令使用&bypath子例程: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;
}
子路径{
my@a=拆分m'/',$a;
my@b=拆分m'/',$b;
对于(我的$i=0;$i$#b;
如果$a[$i]cmp$b[$i],则返回$a[$i]cmp$b[$i];
}
返回$#a$#b;
}
样本结果:
- 这个
- 这个/那个
- 这个/那个/其他
- 这个/那个/其他/文件a
- 这个/那个/其他/fileb
- this/that/other.new/filea
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");
}
更好的方法是,用
@files=readdir(DIR)
@andy lester替换while
循环,因为这样,打印连接(“\n”,排序{$a cmp$b}readdir(DIR))。“\n”
谢谢!我真不敢相信我错过了这么基本的东西。感谢StackOverflow和所有帮助我解决问题的人!同时添加lc
函数避免了名称大写引起的奇怪结果:@files=sort{lc($a)cmp lc($b)}@files;
use v5.10;
say for sort do { opendir( my $fh, $dir ); readdir($fh) };
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");
}