in reply to Re: Sorting path names with Sort::Key
in thread Sorting path names with Sort::Key

A couple of tips:

use Sort::Key::Natural qw( natkeysort ); my @sorted = natkeysort { tr|\\/|\0|r } @paths;

Of course, this still ignores case-insensitive volumes, as well as paths containing «.» and «..». But what can you do? (Well, «.» can be addressed, but there's no obvious solution if any exist for the rest.)

Replies are listed 'Best First'.
Re^3: Sorting path names with Sort::Key
by Anonymous Monk on Jan 10, 2025 at 13:40 UTC
    I would agree if this produced output like keysort but with better number handling, but because the null characters are treated equivalently to any other non-word characters, and natsort splits the words on these, the output differs more than just on numbers. Note that 'abc-def' now sorts before '/abc/def' in the output:
    Ordered with keysort: /abc /abc/1/2/a/b/c /abc/2 /abc/22 /abc/3 /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 Ordered with natkeysort: /abc /abc/1/2/a/b/c /abc/2 /abc/3 /abc/22 /abc-def/1/2/a/b /abc/def/1/2/a/b/c /abc!def/1/2/a/b/c /abcdef/1/2/a/b/c /usr/a
      Sort::Key::Natural provides a low level function mkkey_natural for that:
      # untested use Sort::Key qw(keysort); use Sort::Key::Natural qw(mkkey_natural); @sorted = keysort { join "\x00\x00", map mkkey_natural, split /\//, $_ + } @paths;
      The double 0 char (\x00\x00) is used for joining because mkkey_natural uses a similar trick in the generated keys.
Re^3: Sorting path names with Sort::Key
by Anonymous Monk on Jan 10, 2025 at 18:22 UTC
    Of course, this still ignores case-insensitive volumes, as well as paths containing «.» and «..». But what can you do? (Well, «.» can be addressed, but there's no obvious solution if any exist for the rest.)
    There's also portability issues like what File::Spec handles. Volumes and different path separators, etc. You can also be processing a list of paths generated on a different system (e.g. processing windows paths on unix).