How can I make "ls" show dotfiles first?

21,385

Solution 1

⚠️ This answer is a little dated. Please check out the other answers, particularly those using aliases or ls -v.


Try adding

export LC_COLLATE="C"

in your dotfiles, or changing the LC_ALL assignment to:

export LC_ALL="C"

This controls the way sorting on character level works — while the default would be to sort dotfiles inline, this will make sort list dotfiles first.

However, note that this will basically stop support for your actual locale across all locale-aware utilities.


To go further, quoting the GNU Coreutils manual (emphasis mine):

If you use a non-POSIX locale (e.g., by setting LC_ALL to en_US), then sort may produce output that is sorted differently than you're accustomed to.

In that case, set the LC_ALL environment variable to C. Note that setting only LC_COLLATE has two problems. First, it is ineffective if LC_ALL is also set. Second, it has undefined behavior if LC_CTYPE (or LANG, if LC_CTYPE is unset) is set to an incompatible value. For example, you get undefined behavior if LC_CTYPE is ja_JP.PCK but LC_COLLATE is en_US.UTF-8.

Solution 2

To avoid any system wide changes without real need, one can change only the way how ls works for the current user by adding the alias to the .bashrc:

alias ll='LC_COLLATE=C ls -alF'

This sorts dot files first, allows to properly handle (show and sort) "uncommon" character sets like cyrillic. The only culprit that the sorting will be case-sensitive.

Source: http://ubuntuforums.org/showthread.php?t=816753

Solution 3

The ls(1) manpage lists:

-v natural sort of (version) numbers within text

This seems change how periods are sorted and does group dotfiles first. I have:

alias ls='ls -vAF'
alias ll='ls -l'

in my ~/.bashrc.

Solution 4

Setting

LC_ALL="C.UTF-8"

works fine for me - umlauts and "ls -la" lists dot-files first.

Solution 5

An off the wall idea

Disclaimer: This is going to be overkill for most of you. But I've been doing this since 1995 and I have the skills to make my world exactly how I want it. So, I why not?

I really like using different sorting methods with ls, especially -rt (which is sort by reverse modified time). So, I decided to try something crazy and use awk to do my sorting.

# save as ~/.ls.awk
# inpsired by http://superuser.com/questions/448291/how-can-i-make-ls-show-dotfiles-first

{
    if($1 == "total"){
        print $0
        next
    }
    # may need to adjust $9 to match your name column
    if(match($9, /^(\033\[[0-9]*m)*\./)) # optionally look past xterm highlighting like: ^[[34m
        df[++dd] = $0
    else
        nf[++nn] = $0
}
END{
    while (++d in df)
        print df[d]
    while (++n in nf)
        print nf[n]
}

Now instead of defining a bash alias, I define a bash function (because aliases can only append arguments at the end, but functions can use them anywhere)

ll(){ CLICOLOR_FORCE=1 ls -lhA $* | awk -f ~/.ls.awk; }

To see the results

Let's create some sample files:

for n in 4 .4 3 .3 2 .2 1 .1; do touch $n; sleep 1; done

Using plain ls

$ ls -lA
total 8
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .1
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .2
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .3
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .4
-rwxr-xr-x  1 bbronosky  staff  285 Nov 29 13:14 .ls.awk
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 1
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 2
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 3
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 4
$ ls -lArt

total 8
-rwxr-xr-x  1 bbronosky  staff  285 Nov 29 13:14 .ls.awk
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 4
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .4
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 3
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .3
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 2
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .2
-rwxr-xr-x  1 bbronosky  staff    0 Dec  1 00:25 1
-rw-r--r--  1 bbronosky  staff    0 Dec  1 00:25 .1

Using my function that filters with awk

$ ll
total 8
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .1
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .2
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .3
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .4
-rwxr-xr-x  1 bbronosky  staff   285B Nov 29 13:14 .ls.awk
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 1
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 2
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 3
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 4

$ ll -rt
total 8
-rwxr-xr-x  1 bbronosky  staff   285B Nov 29 13:14 .ls.awk
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .4
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .3
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .2
-rw-r--r--  1 bbronosky  staff     0B Dec  1 00:25 .1
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 4
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 3
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 2
-rwxr-xr-x  1 bbronosky  staff     0B Dec  1 00:25 1

You can see my implementation of this here https://github.com/RichardBronosky/dotfiles/commit/6170c0a9

What's most important about this is that it is a framework for tweaking your ls output. You can do anything you want with that awk filter. You might want it to be directories, then dotfiles, then everything else. Once you know how to handle your xterm colors, it's not too difficult. It's totally up to you.

Share:
21,385

Related videos on Youtube

clang1234
Author by

clang1234

Updated on September 18, 2022

Comments

  • clang1234
    clang1234 almost 2 years

    Somewhere along the way I screwed up my ls command and now I get this ordering when running

    $ ls -AhHl --color=auto
    -rwxr-xr-x 1 clang clang  640 Mar  1 02:46 apple-touch-icon-precomposed.png
    -rwxr-xr-x 1 clang clang  784 Jul 12 02:54 crossdomain.xml
    -rwxr-xr-x 1 clang clang 1.2K Mar  1 02:46 favicon.ico
    drwxr-xr-x 8 clang clang 4.0K Jul 12 23:50 .git
    -rw-r--r-- 1 clang clang   17 Feb 29 19:48 .gitignore
    -rwxr-xr-x 1 clang clang 1.4K Jul 12 02:54 humans.txt
    

    What did I do that made ls ignore the dotfiles and instead order by first letter?

    Output of locale:

    $ locale
    LANG=
    LANGUAGE=
    LC_CTYPE="en_US.UTF-8"
    LC_NUMERIC="en_US.UTF-8"
    LC_TIME="en_US.UTF-8"
    LC_COLLATE="en_US.UTF-8"
    LC_MONETARY="en_US.UTF-8"
    LC_MESSAGES="en_US.UTF-8"
    LC_PAPER="en_US.UTF-8"
    LC_NAME="en_US.UTF-8"
    LC_ADDRESS="en_US.UTF-8"
    LC_TELEPHONE="en_US.UTF-8"
    LC_MEASUREMENT="en_US.UTF-8"
    LC_IDENTIFICATION="en_US.UTF-8"
    LC_ALL=en_US.UTF-8
    
  • clang1234
    clang1234 almost 12 years
    Setting LC_ALL="C" did the trick! Thanks for the quick response
  • ohho
    ohho almost 11 years
    Setting LC_ALL="C" will ls foreign language (e.g. Japanese) unicode filenames as ????????
  • Chnossos
    Chnossos almost 10 years
    dot files are listed first, but now file names that starts with a uppercase letter are listed before those that starts with a lowercase.
  • mklement0
    mklement0 over 9 years
    Note that by adding export LC_ALL="C" to your dotfiles you'll effectively lose support for your actual locale across all locale-aware utilities. While the printing problem that @ohho points out could be remedied with Faroul's answer, you'll introduce sorting problems: sorting will happen by byte value only, resulting in sorting that is (a) unexpectedly case-sensitive, and (b) invariably places accented chars. after all non-accented ones.
  • mklement0
    mklement0 over 9 years
    +1 for coming closer than the accepted answer, but to summarize the limitations: the sorting will become case-sensitive, and foreign characters - while now printed correctly due to UTF-8 - won't be sorted correctly.
  • Software Engineer
    Software Engineer about 9 years
    This is the best answer here by far
  • Martin Tournoij
    Martin Tournoij about 9 years
    C.UTF-8 is an invalid locale, so locale reverts back to C. You still lose UTF-8 support. In fact, it's even worse since LC_ALL=C mostprograms display most multibyte characters correctly, but with LC_ALL=something_invalid some programs don't (like `ls).
  • Gui Ambros
    Gui Ambros about 8 years
    Beautiful. Much better than changing the system-wide configuration (which can cause you problems with some python modules).
  • matty
    matty almost 8 years
    This was the most helpful answer. Additionally, in an environment where LC_ALL is already set to something incompatible with sorting/hoisting dotfiles to the top of the ls listing, use alias ll='LC_ALL=C ls -alF' instead, because LC_COLLATE doesn't override LC_ALL.
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' over 6 years
    What does --group-directories-first have to do with “show dotfiles first”?
  • muru
    muru almost 6 years
    @MartinTournoij but if Stéphane Chazelas says otherwise about GNU systems (so presumably Debian and Linux in general), which is correct?
  • Martin Tournoij
    Martin Tournoij almost 6 years
    @muru I'm not sure, I guess you'll have to ask Stéphane? All I know is that locale seems to error out with LC_ALL=C.UTF-8: gist.github.com/Carpetsmoker/ef09b3734b29372939f97107413d773‌​3 – that is on Arch Linux.
  • muru
    muru almost 6 years
    @MartinTournoij seems it's not enabled on Arch: bugs.archlinux.org/task/32296 (it is on Debian and co, and Fedora as well: bugzilla.redhat.com/show_bug.cgi?id=902094)
  • Martin Tournoij
    Martin Tournoij almost 6 years
    @muru Looks like they included a custom patch against GNU libc, so it's something that may or may not work depending on your Linux/Unix flavour and libc that's being used.
  • Odaya G
    Odaya G about 5 years
    +1 for being creative. Did not work though.
  • George Hawkins
    George Hawkins about 4 years
    I think this answer is a little out of date. At the very least use C.UTF-8, as in @Faroul's answer, as the old non-Unicode variant will cause trouble for things like Python 3 output. But do note, as others have, that locale affects everything, not just ls, so setting the locale to C or C.UTF-8 will e.g. disable spell checking. So best to set your locale appropriately, e.g. to en_US.UTF-8, and go for a solution that only affects ls (like using aliases and the -v flag as in @VinceValenti's answer).
  • Luke
    Luke almost 4 years
    thank you very much for ls -v
  • Luke
    Luke almost 3 years
    thanks for ls -v