Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Sort ls output in true numerical order UNIX
This hint comes from a chat in the Mac OS X Hints IRC channel between "Cougar" and myself ... I'm sure you've seen output like this before from ls:
untitled folder 2
untitled folder 20
untitled folder 21
...
untitled folder 3
untitled folder 30
...
The Finder accounts for the numbers when it sorts in, say, column view, but ls doesn't. Output is sorted in a dictionary-style listing (lexicographical sorting), and can be fairly annoying or useless in some situations. The OS 7 Finder suffered from this problem, too, for those who remember it (an INIT called "Natural Order" solved it). Read the rest of the hint for the solution...

With the sort utility, we can get things looking nice again:
ls | sort -n +2

untitled folder 2
untitled folder 3
untitled folder 20
untitled folder 21
...
Woot! You'll noticed I used +2. A quick glance in the man pages for sort reveals:
A position has the form f.c, where f is the number of the field to use and c is the number of the first character from the beginning of the field (for +pos) or from the end of the previous field (for -pos).
It's fairly easy to understand, but for some reason, well, this is where the Really Hardcore Unix Gurus have to lend additional explanation. The first field is field 0, the second is 1, etc. So to sort on the eighth character of the second field, you'd use sort -n +1.8.

In ideal situations, you could just name your files and folders with leading zeros (001, 010, 100), but this is a great solution to the problem if you can't do that or don't want to for other reasons. Also note that ls -n doesn't work unless the file or folder name starts with a number.

An example of how folder and file name formats can alter how you execute the command can be seen like this:
[thermodynamics:~/Desktop] mikey% ls *folder | sort -n +0.8
untitled3folder:
untitled5folder:
untitled20folder:
untitled40 folder:
If any of you Unix gurus can provide more detail on sort, please do so!
    •    
  • Currently 3.57 / 5
  You rated: 3 / 5 (7 votes cast)
 
[24,072 views]  

Sort ls output in true numerical order | 11 comments | Create New Account
Click here to return to the 'Sort ls output in true numerical order' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Addendum to hint
Authored by: Mikey-San on Jul 25, '03 12:00:04PM

Right after I sent in this hint, it hit me:

It's a coordinate system, as the manual states (hey, I'm not perfect when it comes to reading man pages ;-))

If I have these folders:

test3folder
test40folder
test5folder

I can sort them by using +0.4. Why? The first number, 0, tells sort to search the first field (0 is first field, 1 is second, 2 is third, and so on), and 4 tells sort to sort starting with the fifth character (0 is first, 1 is second, and so on like the first coordinate number).

:-)



[ Reply to This | # ]
Addendum to hint
Authored by: Clewin on Jul 25, '03 01:32:44PM

I've always disliked the terminology of the sort man page, which is pretty much written for advanced programmers - a simpler explanation is that the first value is the word you want to sort on, and the second value is the character in that word. It's actually a bit more complex than that, as it is based on string tokenization (strings are broken up by a character specified by the -t parameter, default is space), but the concept is easier to understand this way.

Remember that the first word is 0, not 1 (this is due to really old legacy issues that also crept into the C language, btw) - here's a table by words:
0 1 2
----------------------------------
untitled folder 1
untitled folder 2
untitled folder 22
untitled folder 3

sort +2 is the same as saying sort +2.0. The 2 is the third word/column above, and the 0 refers to the first character in that column (in order, 1,2,2,3). This obviously won't work as is, as you will get the same order as above. This is where the -n flag comes in - it translates the value to a number first, and then performs the sort. Since 22 comes after 3, it is last in the list when sorted as a number.

Incidentally, there is an alternate way of writing this command, as well.
ls | sort +2n

Alas, not all your problems are solved - if you have something like this:
untitled 1
untitled 22
untitled 3
untitled folder 1
untitled folder 11
untitled folder 2

how do you sort that?

sort has the ability to handle multiple inputs, so you could do something like
ls | sort -d +2n +1n
note the reverse order number sort - if you don't do that, words will take precedence over number (actually, they're viewed as no number) and will appear first - therefore, untitled folder 1 will show up before untitled 1.

unfortunately, adding
'apple folder 1'
will break it again. The solution isn't easy, and I'm pretty sure can't be solved with sort alone, at least not in a case that works for everything. How I would probably handle it:
write a program that does a sort +0
pass matching '0' tokens (e.g. any untitled above) into a second level sort that sorts on +1. Recurse until all tokens are parsed. On the reverse recursion, sort +[level]n so numbers get sorted properly.
alias ls to this program.



[ Reply to This | # ]
Addendum to hint
Authored by: Mikey-San on Jul 25, '03 02:26:59PM

Yeah, the 0 for "first" came as no surprise, but not because I know C or anything . . .

Values in Forge (level editor for Marathon 2/Infinity) begin at 0 and go up from there, usually, as do values in Anvil (physics editor).

:-)



[ Reply to This | # ]
Addendum to hint
Authored by: fenner on Jul 25, '03 05:17:26PM

sort is one of those weird programs that evolved in two different ways in System V and BSD. The +n syntax, zero-based, came from BSD. System V introduced the same functionality with the "-k" flag, which is one-based. So your "sort +2" is the same as "sort -k 3". I don't know if this makes things more or less confusing =)



[ Reply to This | # ]
Sort ls output in true numerical order
Authored by: Mikey-San on Jul 25, '03 12:02:26PM

(So note that the hint itself should read "sort after the eighth character", not "sort on the eighth character".)



[ Reply to This | # ]
Sort ls output in true numerical order
Authored by: McBainLives on Jul 25, '03 07:40:01PM

Personally, I just include leading zeroes in numbers (e.g., "Folder 01) when I expect there to be more than 9 items in the list. No unix needed!



[ Reply to This | # ]
Sort ls output in true numerical order
Authored by: Mikey-San on Jul 25, '03 07:48:57PM

Yeah, that's the ideal way to do it, but what if you can't for some reason? (Make one up.) Coug and I thought it was a neat problem to work on.

Still, though, the leading-zero numbering scheme is the easiest thing, yeah.



[ Reply to This | # ]
Sort ls output in true numerical order
Authored by: bdm on Jul 25, '03 09:52:22PM

The problem with
ls | sort +0.4n
is that you only see one file per line. To correct this you can pipe it through pr as well:
ls | sort +0.4n | pr -at -4
The -4 is the number of columns. -at will sort across the page. If you want sorting down the columns like ls usually does, use something like
ls | sort +0.4n | pr -tl9999 -4

The reason you see only one line per file in the original hint is that ls always does that when writing into a pipe unless you add the -C switch. However -C is no use in this application because the sorting becomes too hard.



[ Reply to This | # ]
Sort::Naturally for more general use
Authored by: schwern on Jul 28, '03 08:41:59PM

Using sort is ok as long as you know before hand what your files are going to look like. For general use, you need something a bit more intellegent. Something that knows how to identify a number and sort them naturally. The Sort::Naturally Perl module can do this:

~/tmp/sort $ ls
23  4  bar  foo  foo10  foo2  foo392  foobar23  foobar4
~/tmp/sort $ perl -MSort::Naturally -wle 'print join "  ", nsort @ARGV' *
4  23  bar  foo  foobar4  foobar23  foo2  foo10  foo392


[ Reply to This | # ]
Sort ls output in true numerical order
Authored by: gizmovision on Aug 03, '03 03:48:26PM

So how do i get it to sort all the time I don't use the terminal or shell scripts that often, is there a helpful something that will act like the Natural Order INIT, which I did use and still have in use on a OS 9 machine...
How can i get the finder to use the Sort-Naturally-1.01 script all the time?
Thanks for your time and patience!

~Joe



[ Reply to This | # ]
Sort ls output in true numerical order
Authored by: ceilingcat on Apr 30, '09 03:18:01PM
not sure if the sort command has changed since the original posts. It doesn't seem to work for me. Using -n I would get
ls | sort -n +0.4
sort: open failed: +0.4: No such file or directory
I looked around a bit and the following seemed to work.
ls | sort -n -k1.5
Where the parameters following -k means the 1st field and starting with the 5th character.

[ Reply to This | # ]