I'm trying to come up with a naming convention for a set of files such that they always sort in a consistent order without requiring any special options, but I'm having a difficult time achieving this.

If I have the following file names: A.jpg, A1.jpg, A-1.jpg, A_1.jpg, when I run ls from the command line with no options (which the man page says will "Sort entries alphabetically") I get the following order:

A-1.jpg, A_1.jpg, A1.jpg, A.jpg

It's unclear to me how this is actually sorting, because "-", "_", and "1" have ASCII values of 45, 95, and 49 so assuming it's sorting everything before the extension this is not in the correct order. Further, if it's including "." that is ASCII value 46 so the second character values would be 45, 95, 49, 46.

If there are no extension, e.g. A, A1, A-1, and A_1 then ls returns this order:

A, A-1, A_1, A1

In this case the ASCII values of the second character are NULL, 45, 95, 48 which also doesn't seem to be in any order but also is not even in the same order as if the extension was missing.

On the other hand, if I look at the directory in the GNOME file manager, I get the following order:

A.jpg, A1.jpg, A-1.jpg, A_1.jpg

which is also the output I get from ls -v of which the man page says "natural sort of (version) numbers within text". In this case it appears to sort with no numbers first, then plain numbers, then prefixes to the number in ASCII order.

I think if I could understand how ls is actually sorting entries "alphabetically" when there are non-alphabetic characters that would go a long way. From my simple test it's obviously not ASCII value order either, which is what I would expect, and it's not even clear exactly how the dot and extension figure into the whole thing. What is ls doing???

Update: I've put some filenames in the order they are displayed with ls along with ASCII values in hexadecimal below:

A       0x41
A-1     0x41 0x2D
A_1     0x41 0x5F
A1      0x41 0x31
A-1.jpg 0x41 0x2D 0x31 0x2E 0x6A 0x70 0x67
A_1.jpg 0x41 0x5F 0x31 0x2E 0x6A 0x70 0x67
A1.jpg  0x41 0x31 0x2E 0x6A 0x70 0x67
AB      0x41 0x42
AB.jpg  0x41 0x42 0x2E 0x6A 0x70 0x67
A.jpg   0x41 0x2E 0x6A 0x70 0x67

Update 2: In response to the comments, the output of type -a ls is:

ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls

LC_COLLATE is not set.

$ set | grep LC_COLLATE
$ echo $LC_COLLATE


1 Answer 1


Given the uncertainty that you point out with ls and variable length/delimited filenames it probably makes sense to use a fixed width format with only alphanumeric characters. Depending on how many files you plan to have this could include fixed width fields for descriptive names as well as indices.

| name field (10 digits, 'x' extended) | index field (6 digits, '0' extended) | '.' | file extension (3 digits) |



I can't do much better than this without knowing more about the relative sizes of categories, but you can obviously adjust the format above to have more index space or more description space (or more of both by making the fixed width longer). To make longer words go last pad description with '0' ('_' worked for me too, but goes against the first part of my answer), to make sure longer words go first pad them with 'z'

  • The main issue with a fixed format is that there are a large number of existing files (> 100,000) which mostly do not have indexes. However, in the case of an occasional name collision this index is needed.
    – Michael
    Feb 7, 2022 at 23:02
  • I might have an somewhat unconventional / awesome solution then. I just tried this on my machine. Give normal alphanumeric names, and if you have an index do as follows: cat.jpg cat.jpg.1 cat.jpg.2 ...
    – Andrew C
    Feb 8, 2022 at 19:09
  • I'll try that... hopefully nothing gets confused with the unconventional "extension"
    – Michael
    Feb 9, 2022 at 0:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .