Monday, March 5, 2018

Setting the LS_COLORS environment variable to enable colorization in the Tree command

I've come to love the use of the Tree command to print a directory listing in hierarchical form.  I often will use it for documentation purposes such as illustrating how a project hierarchy is laid out, identifying where a specific file is located within the project directory, etc.

I will often use Tree to explore a directory that I am not familiar with as well.  For example, if I download an archive file, it can be much quicker to use Tree after archive is uncompressed, than trying to click back and forth through folders to understand the hierarchy and contents.

However, the Tree command requires the LS_COLORS environment variable be set, which is not typically set by default.  Since most of use simply create an alias such as alias ls='ls -color' or, in my case ll='ls -al --color', which provides colorization to directory listings without using LS_COLORS, we don't have much reason for setting the environment variable.

I tracked down a few blog posts and other sources on the interwebs that cover the setting of LS_COLORS, but none of them really stated how to set it, so I'm capturing it here in hopes that it will be useful for others.

DIR_COLORS

Ultimately, most of the posts I found on the interwebs deal with *changing* the default colors, but I simply wanted the default colors set in the environment variable.  For this, we turn to DIR_COLORS.

Per the man page for DIR_COLORS, the default colors "database" resides under /etc/DIR_COLORS.

This file is simply a listing of the default color settings for the types of files that the ls command displays in the terminal.  

The following is a snippet of the section we're interested in.
$ cat /etc/DIR_COLORS
# Coreutils version coreutils-8.23
...

# Below are the color init strings for the basic file types. A color init
# string consists of one or more of the following numeric codes:
# Attribute codes:
# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
# Text color codes:
# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
# Background color codes:
# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
#NORMAL 00 # no color code at all
#FILE 00 # regular file: use no color at all
RESET 0 # reset to "normal" color
DIR 01;34 # directory
LINK 01;36 # symbolic link. (If you set this to 'target' instead of a
# numerical value, the color is as for the file pointed to.)
MULTIHARDLINK 00 # regular file with more than one link
FIFO 40;33 # pipe
SOCK 01;35 # socket
DOOR 01;35 # door
BLK 40;33;01 # block device driver
CHR 40;33;01 # character device driver
ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file
SETUID 37;41 # file that is setuid (u+s)
SETGID 30;43 # file that is setgid (g+s)
CAPABILITY 30;41 # file with capability
STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w)
OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky
STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable

# This is for files with execute permission:
EXEC 01;32
 In the man page for DIR_COLORS, it states that running eval `dircolors some_path/dir_colors` will set the environment variable.  

Alternatively, running `dircolors --print-database ~/.dircolors` will make a copy of the file from /etc/DIR_COLORS in ~/.dircolors where you can override the default colors to your liking.

The color codes can be found here.  Thanks Bartman!

Setting LS_COLORS

Within Cygwin, the LS_COLORS environment variable can be set by simply running `dircolors`:

$ dircolors
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: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:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=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:*.jpg=01;35:*.jpeg=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:*.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:*.axv=01;35:*.anx=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:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:';
export LS_COLORS
This will use the system defaults from the /etc/DIR_COLORS file. 

If you created a local copy to override the default color scheme, you need to identify the file to use by running `dircolors ~/.dircolors`.

Viola!  It's as simple as that and now Tree looks great and makes directory hierarchy illustration and understanding easier and more colorful!


$ tree /etc/X11
/etc/X11
├── app-defaults
│ ├── KOI8RXTerm
│ ├── KOI8RXTerm-color
│ ├── UXTerm
│ ├── UXTerm-color
│ ├── XTerm
│ └── XTerm-color
├── system.XWinrc
├── xinit
│ ├── startxwinrc
│ ├── Xclients
│ ├── Xclients.d
│ │ └── Xclients.xinit-compat.sh
│ ├── xinitrc
│ ├── xinitrc.d
│ │ ├── 00-start-message-bus.sh
│ │ ├── localuser.sh
│ │ └── xdg-user-dirs.sh
│ ├── xinitrc-common
│ └── Xsession
├── Xmodmap
└── Xresources

4 directories, 18 files