Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Ordering numbers the human way

12 views
Skip to first unread message

HamRadio

unread,
May 7, 2013, 2:42:20 PM5/7/13
to
Hi,


I'm on Debian Wheezy and I'd like to understand this strange behaviour:

$ touch 1 2 3 10 20 30 100 200 300

$ ls *
1 2 3 10 20 30 100 200 300

$ LC_ALL="POSIX" ls *
1 2 3 10 20 30 100 200 300

$ LC_ALL="it_IT" ls *
1 2 3 10 20 30 100 200 300

Everything is fine until now, but the problems begin here:

$ echo *
1 10 100 2 20 200 3 30 300

$ LC_ALL="POSIX" echo *
1 10 100 2 20 200 3 30 300

$ LC_COLLATE="POSIX" echo *
1 10 100 2 20 200 3 30 300

$ LC_ALL="it_IT" echo *
1 10 100 2 20 200 3 30 300

$ LC_COLLATE="it_IT" echo *
1 10 100 2 20 200 3 30 300

$ env | grep LC
$
(I have unset all LC_* variables just to make this test)


How can I tell "echo" (but also "cat") to order numbers just like humans
do?


Many thanks in advance for your help.

David Brown

unread,
May 7, 2013, 2:55:50 PM5/7/13
to
How about:

$ echo one > 1
$ echo two > 2
$ echo three > 3
$ echo ten > 10
$ echo twenty > 20
$ echo thirty > 30
$ echo one hundred > 100
$ echo two hundred > 200
$ echo three hundred > 300

$ ls -1 | sort -g
1
2
3
10
20
30
100
200
300

$ ls -1 | sort -g | xargs cat
one
two
three
ten
twenty
thirty
one hundred
two hundred
three hundred



unruh

unread,
May 7, 2013, 2:58:04 PM5/7/13
to
They do not and never have "ordered numbers" They print out what you
tell them.
It is bash which expands the * into a list. It does not sort them, but I
believe generally puts them out by inode number, or by order in this
they are listed in the directory (ie the order they are come across
while scannning the directory list).

Do
/bin/rm 100
touch 101 100
and try it again.

unruh

unread,
May 7, 2013, 3:07:09 PM5/7/13
to
Sorry, I am wrong
From the man page for bash

-------------------------------
Pathname Expansion
After word splitting, unless the -f option has been set, bash scans each word
for the characters *, ?, and [. If one of these characters appears, then the
word is regarded as a pattern, and replaced with an alphabetically sorted
list of file names matching the pattern.
----------------------------------

is expanded and then alphabetically sorted. Alphabetical sorting is
one where the words are sorted by the ascii value of the first letter,
then the second, then the third, etc.

Just like
a ab abc b be bef c cd cde
is sorted in exactly that order, not
a b c ab be cd abc bef cde
which seems to be what you want. Ie, they are not sorted as numbers.

HamRadio

unread,
May 7, 2013, 3:15:30 PM5/7/13
to
Il Tue, 07 May 2013 19:07:09 +0000, unruh ha scritto:

> is expanded and then alphabetically sorted. Alphabetical sorting is
> one where the words are sorted by the ascii value of the first letter,
> then the second, then the third, etc.

Ok, this is fine, the problem is that bash expands the same "*" in two
different ways for "ls" and "echo"...

Robert Heller

unread,
May 7, 2013, 3:24:18 PM5/7/13
to
You really can't. What is happening is that the shell's glob expansion (echo
and cat have nothing to do with this) is doing *alphabetical* ordering by
ASCII (in this case the digits 0-9 have the same character codes in ASCII and
UTF-8). *Alphabeticly* the *string* "100" is < the *string* "2": they are not
numbers, they are character *strings* representing the (textual) *names* of
files.

What you need to do is:

ls -1 *|sort -n|tr '\n' ' '

If you want to pass this to cat, then:

cat `ls -1 *|sort -n|tr '\n' ' '`

or echo:

echo `ls -1 *|sort -n|tr '\n' ' '`

>
>
> Many thanks in advance for your help.
>
>

--
Robert Heller -- 978-544-6933 / hel...@deepsoft.com
Deepwoods Software -- http://www.deepsoft.com/
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments



Aragorn

unread,
May 7, 2013, 4:09:38 PM5/7/13
to
On Tuesday 07 May 2013 21:07, unruh conveyed the following to
comp.os.linux.misc...
Yes, GNU Bash sorts alphabetically, but just for the record, LC_COLLATE
does have an effect here. Don't pin me down on the exceptions, but when
LC_COLLATE is set to _anything other_ than "C" or "POSIX", the
alphabetic sorting will *usually* ignore upper- and lowercase.

Not pertinent to the OP's inquiry, but it's a detail which is all too
often overlooked, which is why I mention it.

--

Bit Twister

unread,
May 7, 2013, 4:17:12 PM5/7/13
to
On Tue, 07 May 2013 20:55:50 +0200, David Brown wrote:
> On 07/05/13 20:42, HamRadio wrote:
>> Hi,
>>
>>
>> I'm on Debian Wheezy and I'd like to understand this strange behaviour:
>>
>> $ touch 1 2 3 10 20 30 100 200 300

Depending on your version of sort,

for x in $(ls | sort -V) ; do echo $x; done

Bruce Stephens

unread,
May 7, 2013, 5:00:28 PM5/7/13
to
No, bash is expanding in the same way. ls sorts, but echo does not.

Oddly, I get exactly the opposite behaviour to you: ls always seems to
give the order you get with echo

1 10 100 2 20 200 3 30 300

unless I specify one of the non-default ordering options (such as -v,
which gives "natural sort of (version) numbers within text"). And echo
gives the order you get with ls:

1 2 3 10 20 30 100 200 300

I know why that is: I'm using zsh and have set the numericglobsort
option.

Robert Heller

unread,
May 7, 2013, 5:43:00 PM5/7/13
to
No it does not! The *ls* command does its sorting separately. That is,

ls *

sorts the results twice -- ls never sees the wild card, but gets an expanded
and sorted (by bash) list of file names, which it then sorts.

By default the first list is already sorted, but doing

ls -ltr *

will resort the list.

unruh

unread,
May 8, 2013, 12:06:09 AM5/8/13
to
On 2013-05-07, HamRadio <toglimi....@toglimi.quipo.it> wrote:
Nope. ls itself orders its output. echo does not. cat does not (They had
better not. That is not what their purpose is).
Bash expands in exactly the same way for all of them.

ls /tmp/xsndtest /tmp/a.pdf
/tmp/a.pdf /tmp/xsndtest*

Note that output is different order than the input.
But if echo or cat did that it would make them completely useless.

>

HamRadio

unread,
May 8, 2013, 3:34:02 AM5/8/13
to
Many thanks to all of you for your helpful explanations.

I solved my problem with:

$ echo $(ls *)
1 2 3 10 20 30 100 200 300

And I understand this was just one of many other ways to get filenames
containing numbers ordered as I need.

Have a good day!

0 new messages