1

I am kinda ingrained with the Windows sort order in my head. Unfortunately Windows doesn't really allow for an easy way to change it.

Is there a way to emulate such sort order using unix tools?

An example if each is a file name

{"Ie4 01", "Ie4!01", "Ie4_01", "Ie4_128", "Ie5", "Ie6", "Ie401sp2","Ie501sp2"}

correct sort order

Ie4 01
Ie4!01
Ie4_01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2
1

GNU sort's version sort (-V) seems to provide that output:

~ printf "%s\n" "Ie5" "Ie6" "Ie4 01" 'Ie4!01' "Ie4_01" "Ie4_128" "Ie401sp2" "Ie501sp2" |
  sort -V
Ie4 01
Ie4!01
Ie4_01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2
  • I prefer it with out the > so its copy and pastable. thank you in practicality folders seem to me folders are listed 1st so I would just need to concat the 2 separated sorted lists. – William Sep 25 '18 at 23:23
1

In case anyone is wanting to separate folders and files like Windows does, you can do this:

ls -d */ -1 | sort -V
ls -p | grep -v / | sort -V
  • 2
    If this was for ls, a new enough GNU ls should also support version sorting (-v or --sort=version) – muru Sep 26 '18 at 2:03
0

If you're not particular about the ordering of the special characters, then zsh's numeric sorting glob qualifier gets close:

Setup

$ touch "Ie5" "Ie6" "Ie4 01" 'Ie4!01' "Ie4_01" "Ie4_128" "Ie401sp2" "Ie501sp2"
$ mkdir Foo Quux Ie7bar

zsh only

$ print -l *(n/) *(n^/)
Foo
Ie7bar
Quux
Ie4 01
Ie4_01
Ie4!01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2

with ls

$ ls -1df *(n/) *(n^/)
Foo
Ie7bar
Quux
Ie4 01
Ie4_01
Ie4!01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2

The flags to ls are:

  • force single-column output (-1) -- simply for ease of viewing
  • do not descend into directories (-d)
  • do not sort the incoming list (-f or -U)

The zsh glob qualifiers say:

  • *(n/) - expand to the list of directories /, ordered numerically
  • *(n^/) - expand to the list of items that are not ^ directories, ordered numerically

I mention a zsh solution just because you can then manipulate the results more easily, without having to worry about quoting filenames or delimiting them with nulls. For example:

$ mine=( *(/n) *(n^/) )
$ for file in "${mine[@]}"; do print -l "$file"; done
Foo
Ie7bar
Quux
Ie4 01
Ie4_01
Ie4!01
Ie4_128
Ie5
Ie6
Ie401sp2
Ie501sp2
$ print -l "${mine[-1]}"
Ie501sp2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.