Introduction
The dircolors
command is used to set the colours various filetypes are shown in by the ls
command. It also affects at least one other command line utility tree
, so there may be other less known utilities affected by this. The changes I'm suggesting here have been unevenly tested across Fedora, Debian, and macOS (two solutions are shown for macOS toward the end of this entry). You'll also need to use ls --color
, but at this point most distros automatically alias ls
to do this for you. While not directly related to this, I recommend also adding (again, usually aliased by most distros) --classify
to help with readability of links, directories, and executables.
Note
I'm Canadian: as far as I'm concerned, the word is spelled "colour." When I reference the utility dircolors
or the environment variable(s) $LS_COLORS
I'll spell them as you'll need to spell them at the command line. But if I'm referencing the word, it's "colour."
I came to this because on both Linux and Mac the default colour for a directory is a dark blue - on a black background in a terminal, this is sometimes unreadable.
I think it's worth pointing out that while very few people and even less versions of Linux still use 16-colour terminals, they do still exist. I think Debian still configures xterm
to be only 16-colours (I'm not sure because I long ago reconfigured it to 256 colours). A lot of the settings below assume your terminals support 256 colours: you should be aware that some terminals and the Linux console don't support this in case you find yourself with things not working as described.
Another assumption that may not suit you is that the terminal background is black. This is true on every machine I run - but I know some people use white backgrounds or other colours. The settings I demonstrate here will need some adjustment in those contexts.
Digging In
ls
decides what colours to apply to different filetypes based on the $LS_COLORS
environment variable. On Raspberry Pi OS (which is approximately Debian 11) this looks like this:
$ echo $LS_COLORS
rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
You could edit this directly. But there's an easier way, which is where the dircolors
command comes into this. To get started, take a look at the output of dircolors --print-database
to see the default set of values - this includes comments, and they're worth reading. To start modifying this "database," run dircolors --print-database > ~/.dircolors
(confirm that file doesn't already exist first). Edit the file (we'll discuss that shortly), then load it back into the current terminal with eval $(dircolors -b ${HOME}/.dircolors)
. (eval
is much maligned - but in this case, dircolors
is producing an environment variable we need to bring into the current environment.) Open ~/.dircolors with your preferred editor - although I highly recommend (Neo)Vim for this as it has a :set ft=dircolors
syntax-highlighting mode that shows any colour codes as the colour they'll appear in the terminal.
As a starting example (as seen in NeoVim with syntax highlighting on):
LINK 44;01;36 ORPHAN 40;31;01 MISSING 01;37;41
(This isn't the default set of colours, and doesn't exactly match what I see in the terminal because of the HTML conversion, but it's close.) LINK tells it how to highlight links, reasonably enough. ORPHAN matches "symlink to nonexistent file, or non-stat'able file," while MISSING is how to highlight the files that orphans point to. Links are bright cyan, an orphan/broken link is bright red, and (if you do ls -l
) the missing file it points to is bright white on a red background. I find broken links being a different colour incredibly useful: it's saved my ass multiple times.
Highlighting is also done by file extension. We'll get to that, and you'll see it a lot in ~/.dircolors.
Colours and Characteristics
Basic colours can be seen in Bash Prompt #1: Colours, to use 256 colours (rather than just 16), see 256 Command Line Colours for the Bash Prompt (#7) and 'ls'/'dircolors'. Here are the colours and characteristics:
- 30-37 for red, green, yellow, blue, magenta, cyan, grey in that order
- 40-47 for the same background colours
- 01;<colour> for bold
- 03; for italics (not sure it works in all terms, but does work in
urxvt
andxterm
) - 04; for underline
- 05; for blink (inconsistent: doesn't work in
urxvt
, does work inxterm
) - there are a lot of other properties ... but they're unsupported or otherwise problematic (see the Bibliography if you're interested in more details)
In ~/.dircolors, 256-colour codes are used like this:
- 38;5;<256-colour-code> for FG
- 48;5;<256-colour-code> for BG
For example, to use the orange mentioned in the other blog entry on a dark gray background for all text files (again seen in NeoVim):
# Text .txt 38;5;208;48;5;236 .text 04;38;5;208;48;5;236
I changed the second one to be underlined as well: this could be useful if you wanted .text files to stand out so you could change them to be just .txt for consistency.
Changing ls Colours on Mac
This is for the default Mac setup. If you want to actually use dircolors
it's possible but well off the beaten path: Changing ls Colours on Mac to use 'dircolors'.
On Mac, you need to set the $LSCOLORS
environment variable by hand (notice no underscore as $LS_COLORS
for dircolors
above, and no dircolors
command available) - but the setting is very different, much more limited, and despite that reduced complexity, even less intuitive. The default (per the Mac ls
man page) looks like this:
LSCOLORS=exfxcxdxbxegedabagacad
The change I needed to make, to make my directories more readable:
LSCOLORS=Defxcxdxbxegedabagacad
export
this variable in your ~/.profile to make changes from the default. Each pair of letters represents the foreground and background colours for a particular set of files, and the first pair is directories. There are 11 pairs, detailed below. I went from ex which is "blue-on-default" to De which is "yellow-on-blue."
The colours, from the man page:
a black b red c green d brown e blue f magenta g cyan h light grey A bold black, usually shows up as dark grey B bold red C bold green D bold brown, usually shows up as yellow E bold blue F bold magenta G bold cyan H bold light grey; looks like bright white x default foreground or background
Likewise from the man page, the order of attributes:
1. directory 2. symbolic link 3. socket 4. pipe 5. executable 6. block special 7. character special 8. executable with setuid bit set 9. executable with setgid bit set 10. directory writable to others, with sticky bit 11. directory writable to others, without sticky bit
Changing ls Colours on Mac to use 'dircolors'
I don't recommend this, but not only can it be done, I'm using this setup on my Mac. But I consider it fragile and poorly tested (I only made the change a couple days ago). Step one: brew install coreutils
. Then add something like the following to your ~/.profile:
if [ -d /usr/local/opt/coreutils/libexec/gnubin/ ]
then
# GNU 'ls' is available, let's use it
alias ls="/usr/local/opt/coreutils/libexec/gnubin/ls"
if [ -e "${HOME}/.dircolors" ]
then
eval $(/usr/local/opt/coreutils/libexec/gnubin/dircolors -b "${HOME}/.dircolors")
else
eval $(/usr/local/opt/coreutils/libexec/gnubin/dircolors -b)
fi
d () { /usr/local/opt/coreutils/libexec/gnubin/ls --color=tty --classify "$@"; }
da () { /usr/local/opt/coreutils/libexec/gnubin/ls --color=tty --classify -A "$@"; }
v () { /usr/local/opt/coreutils/libexec/gnubin/ls --color=tty --classify -l "$@"; }
va () { /usr/local/opt/coreutils/libexec/gnubin/ls --color=tty --classify -lA "$@"; }
else
# with Mac 'ls', "--color=tty" becomes "-G" and "--classify" becomes "-F"
d () { ls -G -F "$@"; }
da () { ls -G -F -A "$@"; }
v () { ls -G -F -l "$@"; }
va () { ls -G -F -lA "$@"; }
fi
IMPORTANT: again, this is NOT well tested, and it's primarily set up to provide my preferred aliases (or functions in this case): d
, da
, v
, and va
. You'll need to adapt it to your own use. One of the nastiest problems from my point of view is that this leaves you with a functioning GNU ls
(by using an alias
to overwrite an existing binary, something I usually recommend against) and if you type man ls
you get the Apple/BSD man page which describes a very different version of ls
. This can be fixed by modifying $MANPATH
, but this leads you further down the rabbit hole ... Your call.
Bibliography
- https://unix.stackexchange.com/questions/94299/dircolors-modify-color-settings-globaly
- https://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences - explanation of ANSI Colour codes and Escape Sequences
man dircolors