普通の文字列比較では、"a999.txt"と"a1000.txt"では、後者が小さいとみなされます。
しかし、後者が大きいと判定したほうが、自然です。
Wind0wsの場合は数値の部分は数値の比較を行ってくれるようで、ファイル名ソートすると、良い感じにやってくれます。
今回はそんな感じにソートします。
単純に考えれば、数字の部分は数値比較、文字列の部分は文字列比較すればいいです。多分。
もっとうまい方法がありそうですが、僕は頭が悪いので思いつきませんでした。
#!/usr/bin/perl use strict; use warnings; use utf8; # カレントディレクトリのファイル名のリストを取得 my @filenames = (<*>); # ソート @filenames = sort { compare($a,$b) } @filenames; # #@filenames = sort @filenames; # 通常ソート # 出力 foreach my $filename(@filenames){ print "$filename\n"; } # 文字列を数値以外の文字列と数値に分割 # abc123def456 => abc|123|def|456 sub split_strnum{ my $str = shift; my @data = (''); my $i=0; my $flag = 0; # 1文字取得 while($str =~/(.)/g){ my $ch = $1; if($ch =~ /\d/){ # 数字 if($flag == 1){ $i++; push @data, ''; } $flag = 2; $data[$i] .= $ch; }else{ # その他 if($flag == 2){ $i++; push @data, ''; } $flag = 1; $data[$i] .= $ch; } } return \@data; } # それっぽい比較関数 sub compare{ my $data1 = split_strnum shift; my $data2 = split_strnum shift; # 二つの配列から最大長取得 my $length = @$data1 < @$data2 ? @$data2 : @$data1; for(my $i=0; $i<$length; ++$i){ my $s1 = $data1->[$i] ? $data1->[$i] : ""; my $s2 = $data2->[$i] ? $data2->[$i] : ""; my $result; if($s1 =~ /^\d+$/ && $s2 =~ /^\d+$/){ # 両方数字 $result = $s1 <=> $s2; }else{ # 数字じゃなかったら文字列で比較 $result = $s1 cmp $s2; } # 等しくないなら比較結果を返す if($result != 0){ return $result; } } # 完全に一致 return 0; }