use List::Util qw(min); my @path = qw( /abc /abc/1/2/a/b/c /abc/2 /abc/def/1/2/a/b/c /abc!def/1/2/a/b/c /abc-def/1/2/a/b /abcdef/1/2/a/b/c /usr/a ); say 'Wanted path order:'; say ' 'x4, $_ for @path; my @sorted = sort @path; say 'Lexical order (default sort):'; say ' 'x4, $_ for @sorted; say 'Ordered by dirname, then basename:'; @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] or $a->[2] cmp $b->[2] } map { [$_, m{^(.*/)?(.*)}s ] } @path; say ' 'x4, $_ for @sorted; say 'Ordered by path components:'; @sorted = sort bypath @path; say ' 'x4, $_ for @sorted; say 'Ordered by path components (with caching):'; @sorted = map { $_->[0] } sort { for my $i (0 .. min $#{$a->[1]}, $#{$b->[1]}) { return $a->[1][$i] cmp $b->[1][$i] if $a->[1][$i] ne $b->[1][$i]; } return $#{$a->[1]} <=> $#{$b->[1]}; } map { [$_, [split '/'] ] } @path; say ' 'x4, $_ for @sorted; exit; # https://stackoverflow.com/questions/5124994/sorting-directory-filenames-with-perl/19506331#19506331 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; }