3

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
William
  • 1,061

3 Answers3

2

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
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
William
  • 1,061
  • 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 02:03
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
muru
  • 72,889
  • 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
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
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255