Join 3,558 readers in helping fund MetaFilter (Hide)


Case-Insensitive LS on Mac OS X?
August 16, 2009 11:03 AM   Subscribe

Unix mavens: is there a way for ls on a Mac OS X install to alphabetize its listing case-insensitively, while still preserving any other ls flags you may be using? If not, does another ls variant offered by anybody offer case-insensitivity, and if so, how can I supplant one with the other, without risk of any harm to anything else on my system? (If it matters, my shell of choice is tcsh.)
posted by WCityMike to Computers & Internet (19 answers total) 3 users marked this as a favorite
 
There's nothing obvious mentioned on the man page, but I guess there might be some legacy compatibility or language setting you could use for this, e.g.

LC_COLLATE=en_us.8859 ls -l

or something similar. No OS X box within reach, though, so I cannot try it out.
posted by effbot at 11:16 AM on August 16, 2009


You can pipe the output to "sort -f", which will sort the results case-insensitively:

ls -whatever | sort -f

though you'll be better off, if you're going to be using ls for something complicated, learning how to use find(1). It's much more powerful and flexible than ls; I know people who've built careers out of really knowing how to use find and xargs.
posted by mhoye at 11:19 AM on August 16, 2009 [1 favorite]


export LC_COLLATE en_US.utf8

should do it... The UTF8 is the important thing, else it will use POSIX/C rules, which is case sensitive.

(NB: Works on Jaunty, not got an OS X box to test.)
posted by benzo8 at 11:20 AM on August 16, 2009


Sorry - that should be:

export LC_COLLATE=en_US.utf8

Typo!
posted by benzo8 at 11:23 AM on August 16, 2009


benzo8, effbot, that doesn't appear to do it.
posted by WCityMike at 11:37 AM on August 16, 2009


Since you're using tcsh instead of bash, you probably need setenv LC_COLLATE en_US.utf8 instead. I don't have a Mac to test this on either.
posted by grouse at 11:41 AM on August 16, 2009


I actually thought of that one, grouse, after looking at my .tcshrc file. None of these worked:

setenv LC_COLLATE en_US.utf8
setenv LC_COLLATE 'en_US.utf8'
setenv LC_COLLATE "en_US.utf8"
setenv LC_COLLATE = en_US.utf8
set LC_COLLATE = en_US.utf8


Also, mhoye, that command kind of works if I try it with pure vanilla ls piped through sort -f, but it doesn't do the trick for the variant I had been using (in other words, "ls -AHhLlTu | sort -f" doesn't do the trick).
posted by WCityMike at 11:45 AM on August 16, 2009


Have a look at this.

See what output you get from:[code]# locale -a[/code]

Make sure you set LC_COLLATE (or LC_LANG to brute force it) to something that exists on your system, and isn't C or POSIX.
posted by benzo8 at 11:56 AM on August 16, 2009


remember that sort can accept keys

ls -AHhLlTu | sort -fk10

is what you want, sort by the first letter of the 10th field (the file name)
posted by jedrek at 11:56 AM on August 16, 2009 [1 favorite]


Weurgh! Apologies for the BBCode [code]!

# locale -a
posted by benzo8 at 11:57 AM on August 16, 2009


Here's another (ugly) way to do it; perl and the Schwartzian Transform to the rescue!

perl -e 'for (map {$_->[0]} sort { $a->[1] cmp $b->[1] } map { [$_, lc($_)] } <your_files>) { print `ls -yourFlags $_`; }'
posted by jozxyqk at 12:06 PM on August 16, 2009


benzo8: "Have a look at this.

See what output you get from:[code]# locale -a[/code]

Make sure you set LC_COLLATE (or LC_LANG to brute force it) to something that exists on your system, and isn't C or POSIX.
"

locale -a produces en_US.UTF-8 as an option; neither doing setenv LC_LANG en_US.UTF-8 nor setenv LC_COLLATE en_US.UTF-8 works as desired. (Ditto with export in bash.)

jozxyqk: "Here's another (ugly) way to do it"

Even replacing with * and -yourflags with -la, I get:
syntax error at -e line 1, near "; }"
Execution of -e aborted due to compilation errors.


Jedrek's looks like the best solution for me thus far. Still, I'm utterly amazed this isn't as simple as an overlooked command-line switch for ls. Seriously, Unix is about 1370% customizable ... for this supersimple thing to have been overlooked ... ?!

posted by WCityMike at 1:27 PM on August 16, 2009


I understand what you mean about the configurability, but really, it is configurable - in the language settings... It just appears that Apple may have broken that in the their implementation of *NIX!
posted by benzo8 at 2:33 PM on August 16, 2009


WCityMike: When you did the replacement of the file list, did you keep the < and > characters there?

For "*" and "-lA", the line would look like:
perl -e 'for (map {$_->[0]} sort { $a->[1] cmp $b->[1] } map { [$_, lc($_)] } <*>) { print `ls -lA $_`; }'

I agree that jedrek's answer is the most sensible one, though.
posted by jozxyqk at 2:58 PM on August 16, 2009


jozxyqk: "WCityMike: When you did the replacement of the file list, did you keep the < and > characters there?"

Nope, but I did that this time, and got:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = (unset),
LC_TIME = "en_US.UTF-8",
LC_MONETARY = "en_US.UTF-8",
LC_MESSAGES = "en_US.UTF-8",
LC_CTYPE = "en_US.UTF-8",
LC_NUMERIC = "en_US.UTF-8",
LC_COLLATE = "en_US.utf8",
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
ls: 2009-08-06: No such file or directory
ls: Notes.txt: No such file or directory
ls: Tracy: No such file or directory
ls: Search: No such file or directory
ls: aaJob: No such file or directory
ls: -: No such file or directory
ls: Budget: No such file or directory
ls: Unemployment.xls: No such file or directory

posted by WCityMike at 3:09 PM on August 16, 2009


Re: the perl stuff:

Short version:
The locale warning seems to reinforce what benzo8 was saying about something in your locale settings being broken or unsupported in OSX, or something like that.

The "no such file or directory" stuff is probably because you have files with spaces in their names, which I didn't have in my test. Put double-quotes around the $_
so ...`ls -lA "$_"`...

If it still isn't working for you, it probably isn't worth either your or my time to debug it further, since I was just tossing a perl one-liner solution at a problem that didn't need it. Using a swiss army knife to pound a nail, as it were. ;)
posted by jozxyqk at 5:46 PM on August 16, 2009


You need to remember that the philosophy of *nix is many small, interchangeable utilities strung together. The fact that there's a sort flag for ls at all sort of flies in the face of that. ;)
posted by jedrek at 3:03 AM on August 17, 2009


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

Short answer: effbot and benzo8 gave you advice that should have worked, and ls appears to be doing everything right, but either the operating system's locale handling or the locale definitions it includes are broken.
posted by JiBB at 1:39 PM on July 9, 2010 [1 favorite]


Thanks, JiBB, for going through all the bother of determining where the problem lied, especially after the thread has been dead for such a long time. I don't really have the expertise necessary to file a bug report on this one with Apple. Is that something you'd know how to do?
posted by WCityMike at 3:21 PM on July 12, 2010


« Older How important are quantitative...   |  Does anyone know of a company ... Newer »
This thread is closed to new comments.