#!/usr/bin/perl my $FOLDER; my $FIELD = 'subject'; my $REVERSE = 1; # -1 means reverse, 1 means forward use lib '/home/mjd/perl/lib'; use MH; my $VSCALE = 1; my $BAD; while (@ARGV) { local $_ = shift; if (/^\+(.*)/) { $FOLDER = $1; } elsif (/^(-f|-fi|-fie|-fiel|-field)$/) { $FIELD = shift; } elsif (/^(?:-v|-ve|-ver|-verb|-verbo|-verbos|-verbose)$/) { $VERBOSE = 1; } elsif (/^(?:-r|-re|-rev|-reve|-rever|-revers|-reverse)$/) { $REVERSE = -1; } elsif (/^-/) { warn "Unrecognized option '$_'\n"; $BAD=1; } else { $BAD=1; } } usage() if $BAD; $FOLDER = MH::current_folder() unless defined $FOLDER; my %field; my $N = my @old_order = sort {$a <=> $b} MH::message_list($FOLDER); my $s = "s" unless $N == 1; $VSCALE *= 3 until $N / $VSCALE < 80; print STDERR "Scanned folder ($N message$s)\n" if $VERBOSE; print STDERR '|', '-' x ceil($N/$VSCALE - 2), "|\n" if $VERBOSE; for my $mn (@old_order) { my $msg = MH::header($mn, $FOLDER); $field{$mn} = $msg->get($FIELD); print STDERR "." if $VERBOSE && $Vcounter++ % $VSCALE == 0; } print STDERR "\nRead messages\n" if $VERBOSE; my @new_order = sort comparator @old_order; @new_number{@new_order} = @old_order; for my $m (keys %new_number) { delete $new_number{$m} if $new_number{$m} == $m; } my $dir = MH::mhpath($FOLDER); while (%new_number) { my ($cur) = keys %new_number; my @chain; do { push @chain, $cur; $cur = delete $new_number{$cur}; } while $cur != $chain[0]; print STDERR "Chain: (@chain)\n" if $VERBOSE; my ($prev, @rest) = reverse @chain; my $TMP = "$prev.TMP"; rename("$dir/$prev", "$dir/$TMP") or die "$prev => $TMP: $!"; for my $cur (@rest) { rename("$dir/$cur", "$dir/$prev") or die "$cur => $prev: $!"; $prev = $cur; } rename("$dir/$TMP", "$dir/$prev") or die "$TMP => $prev: $!"; } sub comparator { my @F = @field{$a, $b}; my @re_count; for my $i (0 .. 1) { for ($F[$i]) { $re_count[$i]++ while s/^re:\s*//i; tr/A-Za-z/a-za-z/; tr/a-z//cd; } } $REVERSE * (lc $F[0] cmp lc $F[1] || $re_count[0] <=> $re_count[1] || $field{$a} cmp $field{$b} ); } sub usage { warn <