Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I spend most of my time working in Unix environments and using terminal emulators. I try to use color on the command line, because color makes the output more useful and intuitive.

What options exist to add color to my terminal environment? What tricks do you use? What pitfalls have you encountered?

Unfortunately support for color varies depending on terminal type, OS, TERM setting, utility, buggy implementations, etc.

Here's are some tips from my setup, after a lot of experimentation:

  1. I tend to set TERM=xterm-color, which is supported on most hosts (but not all).
  2. I work on a number of different hosts, different OS versions, etc. I use everything from MacOSX, Ubuntu Linux, RHEL/CentOS/Scientific Linux and FreeBSD. I'm trying to keep things simple and generic, if possible.
  3. I do a bunch of work using GNU screen, which adds another layer of fun.
  4. Many OSs set things like dircolors and by default, and I don't want to modify this on a hundred different hosts. So I try to stick with the defaults. Instead tweak my terminal's color configuration.
  5. Use color for some unix commands (ls, grep, less, vim) and the Bash prompt. These commands seem to the standard "ANSI escape sequences". For example:

    alias less='less --RAW-CONTROL-CHARS'
    export LS_OPTS='--color=auto'
    alias ls='ls ${LS_OPTS}
    

I'll post my .bashrc and answer my own question Jeopardy Style.

share|improve this question
    
fyi my approach (see answer below) addresses issues with OSX and Linux differences, for example color on one is ls -G and on the other is ls --color-auto –  Michael Durrant Jan 13 at 22:30

13 Answers 13

up vote 52 down vote accepted

Here are a couple of things you can do:

Editors + Code
A lot of editors have syntax highlighting support. vim and emacs have it on by default. You can also enable it under nano.

You can also syntax highlight code on the terminal by using Pygments as a command-line tool.

grep
grep --color=auto highlights all matches. You can also use export GREP_OPTIONS='--color=auto' to make it persistent without an alias. If you use --color=always, it'll use colour even when piping, which confuses things.

PS1
You can set your PS1 (shell prompt) to use colours. For example:

PS1='\e[33;1m\u@\h: \e[31m\W\e[0m\$ '

Will produce a PS1 like:

[yellow]lucas@ubuntu: [red]~[normal]$

You can get really creative with this. As an idea:

PS1='\e[s\e[0;0H\e[1;33m\h    \t\n\e[1;32mThis is my computer\e[u[\u@\h:  \w]\$ '

Puts a bar at the top of your terminal with some random info. (For best results, also use alias clear="echo -e '\e[2J\n\n'".)

Getting Rid of Escape Sequences

If something is stuck outputting colour when you don't want it to, I use this sed line to strip the escape sequences:

sed "s/\[^[[0-9;]*[a-zA-Z]//gi"

If you want a more authentic experience, you can also get rid of lines starting with \e[8m, which instructs the terminal to hide the text. (Not widely supported.)

sed "s/^\[^[8m.*$//gi"

Also note that those ^[s should be actual, literal ^[s. You can type them by pressing ^V^[ in bash, that is Ctrl+V, Ctrl+[.

share|improve this answer
1  
The first PS1 line should read like this: PS1='\e[33;1m\u@\h: \e[31m\W\e[0m\$ '. There is a superfluous x after the fourth backslash. –  Chris May 23 '13 at 7:30
    
@Chris: Quite right, thanks. –  Lucas Jones May 23 '13 at 17:34
1  
Escapes should be enclosed in \[...\] or else commands in second line will overwrite the first line. PS1='[\e[33;1m]\u@\h: [\e[31m]\W\e[0m\$ ' –  yanglifu90 Aug 29 '13 at 19:09

I also use:

export TERM=xterm-color
export GREP_OPTIONS='--color=auto' GREP_COLOR='1;32'
export CLICOLOR=1
export LSCOLORS=ExFxCxDxBxegedabagacad

And if you like colorizing your prompt, defined color vars can be useful:

export COLOR_NC='\e[0m' # No Color
export COLOR_WHITE='\e[1;37m'
export COLOR_BLACK='\e[0;30m'
export COLOR_BLUE='\e[0;34m'
export COLOR_LIGHT_BLUE='\e[1;34m'
export COLOR_GREEN='\e[0;32m'
export COLOR_LIGHT_GREEN='\e[1;32m'
export COLOR_CYAN='\e[0;36m'
export COLOR_LIGHT_CYAN='\e[1;36m'
export COLOR_RED='\e[0;31m'
export COLOR_LIGHT_RED='\e[1;31m'
export COLOR_PURPLE='\e[0;35m'
export COLOR_LIGHT_PURPLE='\e[1;35m'
export COLOR_BROWN='\e[0;33m'
export COLOR_YELLOW='\e[1;33m'
export COLOR_GRAY='\e[0;30m'
export COLOR_LIGHT_GRAY='\e[0;37m'

And then my prompt is something like this:

case $TERM in
     xterm*|rxvt*)
         local TITLEBAR='\[\033]0;\u ${NEW_PWD}\007\]'
          ;;
     *)
         local TITLEBAR=""
          ;;
    esac

local UC=$COLOR_WHITE               # user's color
[ $UID -eq "0" ] && UC=$COLOR_RED   # root's color

PS1="$TITLEBAR\n\[${UC}\]\u \[${COLOR_LIGHT_BLUE}\]\${PWD} \[${COLOR_BLACK}\]\$(vcprompt) \n\[${COLOR_LIGHT_GREEN}\]→\[${COLOR_NC}\] "  

$(vcprompt) is calling a python script in my ~/sbin which prints version control information about the current path. It includes support for Mercurial, Git, Svn, Cvs, etc. The author of the script has the source here.

share|improve this answer
    
See here for the solution to a line problem I got when I used the above PS1: stackoverflow.com/questions/5087036/… –  thoughtadvances Sep 10 '12 at 15:53
    
I've updated the answer to reflect the escaped brackets for the colors in the prompt. Thanks! –  Kris Nov 27 '14 at 7:57
    
$LSCOLORS and $CLICOLOR are for BSD ls. GNU ls (Linux) uses $LS_COLORS with a different syntax. As GNU feels like home to me, I use LSCOLORS=exgxfxDacxBaBaCaCaeaEa to mimic GNU's colors on BSD. –  Adam Katz Jan 12 at 22:22

grep and ls have already been mentioned, if you want a lot more colors check out Generic Coloriser, its initial purpose was to colorize logfiles, but right out of the box it also colorizes ping, traceroute, gcc, make, netstat, diff, last, ldap, and cvs.

It's easily extended if you know regexes. I've added ps and nmap to the list (if you get into grc I'll be more than glad to share the .conf files for those two tools)

(Btw, to install it via synaptic, pacman, and alike you might have better luck searching for "grc")

share|improve this answer
    
grc now supports ps by default. I'd be interested in your nmap colorings. See also my answer for aliasing all of these in a way that will absorb new commands when you upgrade grc. –  Adam Katz Jan 13 at 3:05
    
I noticed that. here's my conf.nmap (and everything else, really) gist.github.com/sygo/844982#file-conf-nmap - I noticed you work in infosec, you might find conf.hexdump interesting, I haven't finished it yet though. –  Sygo Feb 6 at 21:29
    
Thanks @Sygo. I've forked and revised your gist. I've never actually committed data with git (let alone github's gists) and I cannot figure out how to propose merging it back to you (I'm guessing this is because gists are too simplified). –  Adam Katz Feb 7 at 1:54
    
I suspect you can't because it's a gist and not a proper repository. I did check out your fork though and I'm definitely giving your version a go. I'm curious as what that hex dump one will turn into... –  Sygo Feb 7 at 2:48

Set a bold/colored prompt. From cyberciti.biz and the BashFAQ

# 'tput bold' will work regardless of the foreground and background colors.
# Place the tput output into variables, so they are only execd once.
bold=$(tput bold) # This could also be a color.
reset=$(tput sgr0)
export PS1="\u@\[$bold\]\h\[$reset\]:\w \$ "

I've also managed to find color settings which are widely supported, and which don't print gobbledygook characters in older environments (even FreeBSD4!), and seems to work fine if TERM=vt100, xterm, xterm-color. (For the most part). From my .bashrc:

# Set some options, based on the OS
OS=`uname -s` 

case "$OS" in
    "SunOS" ) 
        # Solaris ls doesn't allow color, so use special characters
        LS_OPTS='-F'
        alias  ls='ls ${LS_OPTS}'
        ;;
    "Linux" )
        # GNU ls supports colors!
        # See dircolors to customize colors
        export LS_OPTS='--color=auto' 
        alias  ls='ls ${LS_OPTS}'

        # Get color support for 'less'
        export LESS="--RAW-CONTROL-CHARS"

        # Use colors for less, man, etc.
        [[ -f ~/.LESS_TERMCAP ]] && . ~/.LESS_TERMCAP

        export GREP_OPTIONS="--color=auto"

        ;;
    "Darwin"|"FreeBSD")

        # Most FreeBSD & Apple Darwin supports colors
        export CLICOLOR=true
        # Get color support for 'less'
        export LESS="--RAW-CONTROL-CHARS"

        # Use colors for less, man, etc.
        [[ -f ~/.LESS_TERMCAP ]] && . ~/.LESS_TERMCAP

        export GREP_OPTIONS="--color=auto"
        ;;
    * ) 
        echo "Unknown OS [$OS]"
        ;;
esac
share|improve this answer
    
Or if you want to use ZSH, Phil Gold's prompt at aperiodic.net/phil/prompt is a work of art. –  tsvallender Aug 12 '10 at 9:27

There's a good tool for setting up your colours for the ls command - http://geoff.greer.fm/lscolors/

share|improve this answer

Some text decoration (bold) to easily differentiate between root and non-root shell. For Zsh:

if test $UID = 0
    then PS1="%B${PS1}%b "
fi

For Bash:

if test $UID = 0
    then PS1="\033[1m${PS1}\033[0m"
fi
share|improve this answer
    
Please specify your shell. The question's only shell specific tag is bash, but I feel your code is not bash. –  manatwork Jan 26 '12 at 9:21
    
@manatwork: sorry, forgot to mention that it was Zsh. Updated my post. –  Mischa Arefiev Jan 26 '12 at 9:53

I just wondered the same thing. I have my own approach, but I'm looking for alternatives.

I write bash wrappers around program calls and pipe their output though sed. What I like about sed is that it will modify and echo each line right away => not much buffering. However, I dislike that for every call to a wrapped program the sed code is parsed and compiled.

For example this is what I do to color the output of ip:

#
# Colorcodes
#
NORMAL=`echo -e '\033[0m'`
RED=`echo -e '\033[31m'`
GREEN=`echo -e '\033[0;32m'`
LGREEN=`echo -e '\033[1;32m'`
BLUE=`echo -e '\033[0;34m'`
LBLUE=`echo -e '\033[1;34m'`
YELLOW=`echo -e '\033[0;33m'`


#
# command: ip
# highlight ip addresses, default route and interface names
#

IP4=$GREEN
IP6=$LBLUE
IFACE=${YELLOW}
DEFAULT_ROUTE=$LBLUE

IP_CMD=$(which ip)

function colored_ip()
{
${IP_CMD} $@ | sed \
    -e "s/inet [^ ]\+ /${IP4}&${NORMAL}/g"\
    -e "s/inet6 [^ ]\+ /${IP6}&${NORMAL}/g"\
    -e "s/^default via .*$/${DEFAULT_ROUTE}&${NORMAL}/"\
    -e "s/^\([0-9]\+: \+\)\([^ \t]\+\)/\1${IFACE}\2${NORMAL}/"
}

alias ip='colored_ip'
share|improve this answer

I've honed my .bashrc over the years to work on both OSX and Ubuntu.
I've also reduced it in size to 28 lines with compact condition statements.
With it, my PS1 prompt looks like: enter image description here

with time in red, username in green, machine name in light blue, pwd in darker blue and git branch in yellow.

Feature of my PS1 prompt:

  • shows git branch!
  • long directory paths (more than 6 elements) are 'trimmed' to show top 3 and bottom 3 directories with _ between then (that's the pwd sed part of LOCATION).
  • carriage return at the end so that prompt is always on the left!

The relevant lines from my .bashrc file are:

git_branch () { git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'; }
HOST='\033[02;36m\]\h'; HOST=' '$HOST
TIME='\033[01;31m\]\t \033[01;32m\]'
LOCATION=' \033[01;34m\]`pwd | sed "s#\(/[^/]\{1,\}/[^/]\{1,\}/[^/]\{1,\}/\).*\(/[^/]\{1,\}/[^/]\{1,\}\)/\{0,1\}#\1_\2#g"`'
BRANCH=' \033[00;33m\]$(git_branch)\[\033[00m\]\n\$ '
PS1=$TIME$USER$HOST$LOCATION$BRANCH
PS2='\[\033[01;36m\]>'

For ls with colors when available and no errors when not (i.e. OSX):

ls --color=al > /dev/null 2>&1 && alias ls='ls -F --color=al' || alias ls='ls -G'
share|improve this answer
    
Colors are available for ls on OS X, but it is done by using export CLICOLOR=1. –  ThomasW Mar 4 at 9:47

You can try a project that helps on colorizing scripts output also, its named ScriptEchoColor at source forge: http://scriptechocolor.sourceforge.net/

ex.:

echoc "@{lr}text output in light red"
echoc "@{bLGu}text outpus in blue, light green background and underlined"
echoc "you @{lr} can @{bLGu} mix @{-a} it all too"
echoc -x "ls" #executes ls command and colorizes it automatically to be easy to be seen

The automatic colors are configurable.

This is an example done with it: enter image description here

share|improve this answer

Colors for man pages (via ArchWiki):

function _colorman() {
  env \
    LESS_TERMCAP_mb=$(printf "\e[1;35m") \
    LESS_TERMCAP_md=$(printf "\e[1;34m") \
    LESS_TERMCAP_me=$(printf "\e[0m") \
    LESS_TERMCAP_se=$(printf "\e[0m") \
    LESS_TERMCAP_so=$(printf "\e[7;40m") \
    LESS_TERMCAP_ue=$(printf "\e[0m") \
    LESS_TERMCAP_us=$(printf "\e[1;33m") \
      "$@"
}
function man() { _colorman man "$@"; }

Colors for grep (1;32 is bright green, see other posts here for other colors):

GREP_OPTIONS='--color=auto'
GREP_COLOR='1;32'

More colors for GNU ls:

# use the config at ~/.dircolors if it exists, otherwise generate anew
eval `dircolors --sh $(ls -d ~/.dircolors 2>/dev/null)`

# Usage: _ls_colors_add BASE NEW [NEW...]
# Have LS color given NEW extensions the way BASE extension is colored
_ls_colors_add() {
  local BASE_COLOR="${LS_COLORS##*:?.$1=}" NEW
  if [ "$LS_COLORS" != "$BASE_COLOR" ]; then
    BASE_COLOR="${BASE_COLOR%%:*}"
    shift
    for NEW in "$@"; do
      if [ "$LS_COLORS" = "${LS_COLORS#*.$NEW=}" ]; then
        LS_COLORS="${LS_COLORS%%:}:*.$NEW=$BASE_COLOR:"
      fi
    done
  fi
  export LS_COLORS
}

_ls_colors_add zip xpi jar
_ls_colors_add ogg opus

alias ls="ls -ph --color=auto"

Install grc (Generic Colouriser) and add it to your aliases:

# using this as a variable allows easier calling down lower
export GRC='grc -es --colour=auto'

# loop through known commands plus all those with named conf files
for cmd in g++ head ld ping6 tail traceroute6 `locate grc/conf.`; do
  cmd="${cmd##*grc/conf.}"  # we want just the command
  # if the command exists, alias it to pass through grc
  type "$cmd" >/dev/null 2>&1 && alias "$cmd"="$GRC $cmd"
done

# ./configure needs special handling: does it exist and is it executable?
alias configure="[ -x ./configure ] && $GRC ./configure"

# GRC plus LS awesomeness (assumes you have an alias for ls)
unalias ll 2>/dev/null
if ls -ld --color=always / >/dev/null 2>&1; then GNU_LS=true; fi
function ll() {
  local color= CLICOLOR_FORCE
  if [ -t 1 ] || [ "$CLICOLOR_FORCE" = true ]; then
    if [ -n "$GNU_LS" ]; then color="--color=always"; fi
    CLICOLOR_FORCE=true
  else
    CLICOLOR_FORCE=
  fi
  $GRC `alias ls |awk -F "'" '{print $2}'` -l $color ${1+"$@"}
}

Colors for diff: Too much content for a function, use a script and alias it in your rc file (unnecessary if you installed grc):

#!/usr/bin/perl
use strict;
use warnings;

open (DIFF, "-|", "diff", @ARGV) or die $!;

my $ydiff = 1;
while (<DIFF>) {
  if (not -t 1) {
    print;
    next;
  }
  chomp;
  $ydiff = 0 if /^[ <>\@+-]/ or ($. == 1 && /^\d+[a-z]{1,5}\d+$/);
  my $color = "";
  if (! $ydiff && /^[\@+-<>]/) {
    $color = (/^[<-](?!--$)/ ? 1 : /^[+>]/ ? 2 : 5);
  } elsif ($ydiff && /\t {6}([<|>])(?:\t|$)/) {
    $color = ($1 eq "<" ? 1 : $1 eq ">" ? 2 : 4);
  }
  $color ? printf ("\e[1;3%dm%s\e[0;0m\n",$color,$_) : print "$_\n";
}
close DIFF;

Colors for bash prompt:

# Shorten home dir, cygwin drives, paths that are too long
# (just bourne; no perl, sed, or bashisms!)
function PSWD() {
  local p="$*" parta partb
  if [ "$p" = "${HOME:-empty}${p#$HOME}" ]
    then p="~${p#$HOME}"
  fi
  # Fix Cygwin drive designations
  if [ "$OS" != "${OS#*CYGWIN}" -a "${p#/cygdrive}" != "$p" ]; then
    p="${p#/cygdrive/}"
    parta="${p%%/*}"
    if [ -z "$parta" ]
      then p="$p:"
      else p="$parta:${p#?}"
    fi
  fi
  # if the resulting path is 34+ characters, truncate it
  parta="${p#??????????????????????????????????}"
  if [ "${parta:-$p}" != "$p" ]; then
    parta="${p#??????????}"     # the path, minus the first 10 chars
    parta="${p%$parta}"         # the first 10 chars of the path
    partb="${p%????????????????????}"   # the path, minus the last 20 chars
    partb="${p#$partb}"         # the last 20 chars of the path
    p="$parta...$partb"         # 10 chars plus 3 dots plus 20 chars = 33
  fi
  echo "$p"
}

PSC() { echo -ne "\[\033[${1:-0;38}m\]"; }
PR="0;32"       # default color used in prompt is green
if [ "$(id -u)" = 0 ]; then
    sudo=41     # root is red background
  elif [ "$USER" != "${SUDO_USER:-$USER}" ]; then
    sudo=31     # not root, not self: red text
  else sudo="$PR"   # standard user color
fi
PROMPT_COMMAND='[ $? = 0 ] && PS1=${PS1[1]} || PS1=${PS1[2]}'
PSbase="$(PSC $sudo)\u$(PSC $PR)@\h $(PSC 33)\$(PSWD \w)"
PS1[1]="$PSbase$(PSC $PR)\$ $(PSC)"
PS1[2]="$PSbase$(PSC  31)\$ $(PSC)"
PS1="${PS1[1]}"
unset sudo PR PSbase

demo of bash prompt

share|improve this answer

I suggest you check out ZSH and its plugin oh-my-zsh which has one of the most powerfull console features that I saw. One of them is picking theme for your terminal. This is example of my theme... In tty the colors are not so warm but they are the same like in this picture... Any way you will love it!

enter image description here

share|improve this answer

For Mac you can use following as specified here

if [ "$TERM" = xterm ]; then TERM=xterm-256color; fi
share|improve this answer

For setting the prompt, I have this in my .bashrc file.

#Set variables for foreground colors
fgRed=$(tput setaf 1)     ; fgGreen=$(tput setaf 2)  ; fgBlue=$(tput setaf 4)
fgMagenta=$(tput setaf 5) ; fgYellow=$(tput setaf 3) ; fgCyan=$(tput setaf 6)
fgWhite=$(tput setaf 7)   ; fgBlack=$(tput setaf 0)
#Set variables for background colors
bgRed=$(tput setab 1)     ; bgGreen=$(tput setab 2)  ; bgBlue=$(tput setab 4)
bgMagenta=$(tput setab 5) ; bgYellow=$(tput setab 3) ; bgCyan=$(tput setab 6)
bgWhite=$(tput setab 7)   ; bgBlack=$(tput setab 0)
#Set variables for font weight and text decoration
B=$(tput bold) ; U=$(tput smul) ; C=$(tput sgr0)
#NOTE: ${C} clears the current formatting

if [[ $USER = "root" ]]; then
  PS1="${B}${fgRed}\u${C}@\h(\s): ${fgGreen}\w${C} > "
else
  PS1="${B}${fgCyan}\u${C}@\h(\s): ${fgGreen}\w${C} > "
fi

This gives me a prompt that looks something like this:

user@host(bash): ~/bin >

The working directory is in green. And the user name is bold and cyan unless I ran the shell with sudo, in which case the user name ("root") displays bold and red.

I personally really like having the formatting control characters stored in variables because it makes reading the code for setting the prompt easier. It also makes editing the prompt much easier.

The reason I use tput is that it's supposed to be more universally supported than the weird 033[01;31m\] sequences. Also, as an added bonus, if you do echo $PS1 at the prompt, you will see the raw prompt with colors instead of those unintelligible control sequences.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.