40

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?

2
  • If it helps: apple.stackexchange.com/a/22304/8546 observes that HFS Plus is usually configured to be case insensitive but case preserving. Feb 14, 2013 at 19:43
  • 1
    Note for Googlers: macOS sort and ls also respects LC_COLLATE, but the LC_COLLATE definition for locales like en_US.UTF-8 is just a symlink that makes it behave like C locale. See mike's answer below for more details. Jul 14, 2022 at 0:45

10 Answers 10

20
+50

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
2
  • 2
    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, 2013 at 13:42
  • Recent Googlers note: ls and sort do indeed respect LC_COLLATE, but the definitions for LC_COLLATE are different in BSD/macOS compared to Linux. See the answer, which currently has many fewer votes. Jul 13, 2022 at 19:48
6

Update as of Aug 1, 2021:

ls -alFG

Explanations:

-a      Include directory entries whose names begin with a dot (.).
-l      (The lowercase letter ``ell''.)  List in long format.  (See below.)  A total sum for all the file sizes is output on a line before the long
        listing.
-F      Display a slash (`/') immediately after each pathname that is a directory, an asterisk (`*') after each that is executable, an at sign (`@')
        after each symbolic link, an equals sign (`=') after each socket, a percent sign (`%') after each whiteout, and a vertical bar (`|') after
        each that is a FIFO.
-G      Enable colorized output.  This option is equivalent to defining CLICOLOR in the environment.  (See below.)

Old:

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

ls -f1 -alFG

It lists all details and sorts them by ignoring case.

3
  • 3
    This doesn't seem to work with macOS 11.4 anymore (I get a truly unsorted listing probably reflecting the order in the filesystem).
    – cbrnr
    Jul 30, 2021 at 9:43
  • @cbrnr Why downvote? I wrote this answer 7+ years ago. If you have a suggestion, suggest it. Aug 1, 2021 at 19:08
  • 1
    I downvoted because your answer doesn't work anymore on macOS 11.4. However, the title specifically mentions OS X Lion, so I removed my downvote because it might still work there. The best solution on 11.4 seems to be coreutils and gls.
    – cbrnr
    Aug 2, 2021 at 5:40
5

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

Adding to Mike's answer, 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.

2
  • perhaps consider using /usr/local/share/locale for your custom definition, which man setlocale indicates is also respected, and by default seems to only contain LC_MESSAGES for various locales. Jul 13, 2022 at 19:20
  • @mmmmmm could you fix your edit -- you introduced a grammar problem Jul 15, 2022 at 16:13
2

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
  • 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, 2011 at 8:51
2

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.

1
  • indeed, if you look in /usr/share/locale, many LC_COLLATE files (e.g. en_US.UTF-8) are a symlink to la_LN.US-ASCII, which sorts uppercase before lowercase. cs_CZ.ISO8859-2 has its own LC_COLLATE file. Jul 13, 2022 at 19:26
2

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, but that doesn't bother me.

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

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.

UPDATE: Per user1561489's suggestion in comments, I had success with the following more efficient line placed in the /etc/bashrc file.

alias ls="LC_COLLATE=cs_CZ.ISO8859-2 ls -AlhF"
5
  • The best answer, but the example given does too much. It should be trimmed down to: put the following line into your .bashrc or .zshrc: alias ls="LC_COLLATE=cs_CZ.ISO8859-2 ls"
    – raarts
    Nov 22, 2019 at 11:02
  • @user1561489, I tried your suggestion, but it didn't work for me.
    – Jer
    Jan 26, 2020 at 19:02
  • 1
    I just tried it again and it works for me in Catalina. Try make a temp directory and put two files in it: README and dontreadme. Normally ls will show README first. if I enter alias ls="LC_COLLATE=cs_CZ.ISO8859-2 ls" on the prompt and do ls again it will list dontreadme first
    – raarts
    Jan 27, 2020 at 22:31
  • You're right. Worked in Mojave. I put the following in /etc/bashrc: alias ls="LC_COLLATE=cs_CZ.ISO8859-2 ls -AlhF". Added your suggestion as an update to my post, @user1561489.
    – Jer
    Jan 28, 2020 at 12:26
  • might want to alias the sort command in the same way, depending on what your goals are Jul 13, 2022 at 19:38
1

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.

2
  • 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, 2014 at 0:12
  • 3
    The other problem (now) is that this doesn't seem to work anymore under macOS >= 10.13 due to the new APFS. Nov 11, 2017 at 13:18
0

Run:

$ type ls

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

2
  • 1
    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, 2011 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, 2011 at 23:08
0

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.)

You must log in to answer this question.