How can I make the ls command in Max OS X Lion sort files and directories similar to how Ubuntu Linux does (case-insensitive, directories NOT on top, dot files NOT on top)? Ideally I'd like to do this without piping output to another command such as sort.

For example, I want to see:

foo
Foobar
MyStuff/
.stuff/
test.txt

instead of:

.stuff
Foobar
MyStuff/
foo
test.txt

In Linux, ls sort order is controlled by the system's locale, specifically LC_COLLATE. When LC_COLLATE=en_US.UTF-8, ls will sort items like I want. When LC_COLLATE=C, ls will sort similar to OS X.

LC_COLLATE is set to en_US.UTF-8 in OS X, but ls still sorts the old POSIX way. Does anyone know how I can make this behave more like Linux?

migrated from serverfault.com Dec 18 '11 at 7:09

This question came from our site for system and network administrators.

10 Answers 10

It might not be possible:

Taking a look at the source code for ls, it uses strcoll to sort the filenames, and so should respect LC_COLLATE.

Some postings online suggest that the locales in BSD (and Darwin/OS X) are somewhat broken compared to those in Linux. I wrote a quick sorting program of my own which explicitly set it's locale and tested it using both the en_US.UTF-8 and C locales on my machine (Mac OS 10.6.3) and a university machine (Linux, FC11?). While sorting works as expected on the linux machine, ("a B c" vs "B a c"), the mac always sorts them as "B a c".

Source: http://ask.metafilter.com/130292/CaseInsensitive-LS-on-Mac-OS-X

ORIGINAL ANSWER

This command does not sort dot files, but shows additional directory listings

ls -f1 

I got close to this:

.
..
.stuff
foo
Foobar
MyStuff
test.txt
  • 1
    Interesting that "disabling sort" with the -f option actually seems to sort it as expected. I assume this is the filesystem/HFS+ sorting entries with a more "natural" collation. – Gerry Feb 15 '13 at 13:42

I know this has been answered but this work best for me:

ls -f1 -alF -G

It lists all details and sorts them by ignoring case.

Adding to what Mike wrote above, I've taken it a bit further and found a way to define your own collation rules.

The locale definitions are located in /usr/share/locale/. Each folder is a locale and has a file (or a link) LC_COLLATE, which defines which symbols are "same" (for example, that U, u and ü should be considered the same when ordering). You can duplicate a directory and this will create a new locale definition:

$ sudo cp -R en_GB.UTF-8/ en_GB.UTF-8-CI/

Now you'll have a new locale called 'en_GB.UTF-8-CI' ('CI' for case-insensitive) and you can use LC_COLLATE from there.

Now, to change LC_COLLATE in the new locale you can download the locale sources from http://www.opensource.apple.com/source/adv_cmds/adv_cmds-119/usr-share-locale.tproj/colldef/, edit the one that's closest to what you want and run

$ colldef < <new collation file>
$ sudo cp LC_COLLATE /usr/share/locale/en_GB.UTF-8-CI/

and now when you run

$ LC_COLLATE=en_GB.UTF-8-CI ls

you will have sorting according to your rules.

Yes, this is what it takes to make 'ls' sort case-insensitive.

This has been bugging me for awhile now, and I finally got it sorted (heh). After trying a bunch of suggestions that didn't work, here's what did.

If you're willing to install MacPorts (or Homebrew, or Fink), the GNU version of ls does exactly what you want. I use MacPorts, myself, so that's the approach I'll explain:

  1. Download and install MacPorts:

    http://www.macports.org

  2. Install the GNU Coreutils package:

    sudo port install coreutils

  3. You should now have GNU ls: gls. Try it in a directory that contains items that start with both uppercase and lowercase letters:

    gls -U

    (The -U option actually means "unsorted", but on OS X that has the desired effect of making it case insensitive.)

  4. Add this alias in your .bash_profile so the regular ls will work the way you want it to (I like the color output, but you can omit that if you want; you only need the -U):

    alias ls='gls -U --color'

Note that the -U option probably won't work on other platforms. In OS X, it always seems to do the right thing (maybe because HFS+ is effectively case-insensitive -- "case-aware", technically), but if you try it on a Linux box, the results will most likely just not be sorted at all.

  • 3. does not seem to have the desired side-effect anymore (-U option) under macOS >= 10.13 due to the new APFS. – Marius Hofert Nov 11 '17 at 13:18
  • Yep…doesn't look like there's any way to do this with APFS. – Jason Sims Dec 23 '17 at 20:28
  • Confirm does work on 10.12 though. Thanks! – Colonel Panic May 1 at 17:02

As a workaround you can use a function and an alias:

function lssorted() { /bin/ls "$@" | sort -f ;}
alias ls='lssorted'

This produces a case insensitively sorted output for the standard ls command.

  • 1
    I have to note: this will fail if for example -l is used. Then ls produces another line "total X" at the beginning, which will also be sorted. – Arne Dec 22 '11 at 8:51

Using

ls -f

works for me.

-f officially switches off any sorting, but it looks like then the original HFS sort shines through, which is exactly a case-insensitive sort.

I guess, it actually depends on whether you have your HD formated case-sensitive or not, but as case-INsensitive HFS format is the default for Mac OS X system disks, this should work for the majority of users.

  • This is definitely the right answer. The only issue with it is that it implicitly turns on -a as well, and there's no way to turn that off, which will show you files/folders beginning with a period, including . and .. . – lensovet Dec 12 '14 at 0:12
  • The other problem (now) is that this doesn't seem to work anymore under macOS >= 10.13 due to the new APFS. – Marius Hofert Nov 11 '17 at 13:18

Run:

$ type ls

You'll probably find that your ls command is aliased.

  • On linux: ls is /bin/ls. On OS X: ls is hashed (/bin/ls). Either way, even if I call /bin/ls directly it still doesn't sort according to LC_COLLATE. – blt04 Oct 13 '11 at 22:37
  • 2
    That's surprising, I would have wagered that your ls command was aliased to include --group-directories-first. It may still be done somewhere else, just not an alias. – MikeyB Oct 13 '11 at 23:08

If you are mainly concerned with the sort order of the dot files, you can sort by extension: Use the ls command from the GNU Fileutils with the option --sort=extension. (You can install the GNU Fileutils e.g. through macports.)

ls is sorting according to LC_COLLATE, it's just that most all of the LC_COLLATE files are set to do case sensitive sorting. http://collation-charts.org/fbsd54/

There are two that are set for case insensitive sorting: cs_CZ.ISO8859-2 and et_EE.ISO8859-15 et_EE.ISO8859.15 doesn't sort "Z" the way english speakers would want. cs.CZ.ISO8859-15 does a good job with the alphabet, I just wish it would sort "~" before alphabetic characters.

My solution is: LC_COLLATE=cs_CZ.ISO8859-2 /bin/ls -FG

I wonder if a custom LC_COLLATE file could be made to handle "." the way you want and "~" the way I want.

Inspired by Mike's answer, I added the following to /etc/bashrc, and it works beautifully in Mojave. It lists hidden files at the end when -a is added, but that doesn't bother me.

export LC_COLLATE="cs_CZ.ISO8859-2"; alias ls='ls -lhFG'

You can see the new configuration by running the locale command. To revert, just remove the line from /etc/bashrc and log back into terminal.

$ locale
LANG="en_US.UTF-8"
LC_COLLATE="cs_CZ.ISO8859-2"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL=

Note that neither ls -f1 nor ls -f worked for me in Mojave. I ended up with a truly unsorted list. Only the solution I have provided worked for me in Mojave.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.