Colorizing your terminal and shell environment?

867,562

Solution 1

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.

ls

ls --color=always

Colors specified by:

export LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33'

(hint: dircolors can be helpful)

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 + [.

Solution 2

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_BLACK='\e[0;30m'
export COLOR_GRAY='\e[1;30m'
export COLOR_RED='\e[0;31m'
export COLOR_LIGHT_RED='\e[1;31m'
export COLOR_GREEN='\e[0;32m'
export COLOR_LIGHT_GREEN='\e[1;32m'
export COLOR_BROWN='\e[0;33m'
export COLOR_YELLOW='\e[1;33m'
export COLOR_BLUE='\e[0;34m'
export COLOR_LIGHT_BLUE='\e[1;34m'
export COLOR_PURPLE='\e[0;35m'
export COLOR_LIGHT_PURPLE='\e[1;35m'
export COLOR_CYAN='\e[0;36m'
export COLOR_LIGHT_CYAN='\e[1;36m'
export COLOR_LIGHT_GRAY='\e[0;37m'
export COLOR_WHITE='\e[1;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.

Bash prompt screenshot

This is the full source of my prompt configuration:

Solution 3

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

Solution 4

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'

Solution 5

Colors for man pages (more detail):

function _colorman() {
  env \
    LESS_TERMCAP_mb=$'\e[1;35m' \
    LESS_TERMCAP_md=$'\e[1;34m' \
    LESS_TERMCAP_me=$'\e[0m' \
    LESS_TERMCAP_se=$'\e[0m' \
    LESS_TERMCAP_so=$'\e[7;40m' \
    LESS_TERMCAP_ue=$'\e[0m' \
    LESS_TERMCAP_us=$'\e[1;33m' \
    LESS_TERMCAP_mr=$(tput rev) \
    LESS_TERMCAP_mh=$(tput dim) \
    LESS_TERMCAP_ZN=$(tput ssubm) \
    LESS_TERMCAP_ZV=$(tput rsubm) \
    LESS_TERMCAP_ZO=$(tput ssupm) \
    LESS_TERMCAP_ZW=$(tput rsupm) \
    GROFF_NO_SGR=1 \
      "$@"
}
alias man="LANG=C _colorman man"
function perldoc() { command perldoc -n less "$@" |man -l -; }

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

GREP_OPTS='--color=auto'      # for aliases since $GREP_OPTIONS is deprecated
GREP_COLOR='1;32'             # (legacy) bright green rather than default red
# (new) Matching text in Selected line = green, line numbers dark yellow
GREP_COLORS="ms=${GREP_COLOR}:mc=${GREP_COLOR}:ln=33"
alias grep='grep $GREP_OPTS'
alias egrep='grep -E $GREP_OPTS'
alias fgrep='LC_ALL=C grep -F $GREP_OPTS'

Using LC_ALL=C for fgrep can provide a 140x performance boost

More colors for GNU ls:

# use the config at ~/.dircolors if it exists, otherwise generate anew
eval "$( dircolors --sh $(find ~/.dircolors -size +0 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 jar xpi            # archives
_ls_colors_add jpg ico JPG PNG webp   # images
_ls_colors_add ogg opus               # audio (opus now included by default)

export CLICOLOR=1   # BSD auto-color trigger (like  ls -G  but for everything)
if ls -ld --color=auto / >/dev/null 2>&1
  then alias ls="ls -ph --color=auto"
  else alias ls="ls -ph"
fi

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

if type grc grcat >/dev/null 2>&1; then
  colourify() {  # using this as a function allows easier calling down lower
    if [[ -t 1 || -n "$CLICOLOR_FORCE" ]]
      then ${GRC:-grc} -es --colour=auto "$@"
      else "$@"
    fi
  }

  # 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
    type "$cmd" >/dev/null 2>&1 && alias "$cmd"="colourify $cmd"
  done

  # This needs run-time detection. We even fake the 'command not found' error.
  configure() {
    if [[ -x ./configure ]]; then
      colourify ./configure "$@"
    else
      echo "configure: command not found" >&2
      return 127
    fi
  }

  unalias ll 2>/dev/null
  ll() {
    if [[ -n "$CLICOLOR_FORCE" || -t 1 ]]; then  # re-implement --color=auto
      ls -l --color=always "$@" |grcat conf.ls
      return ${PIPESTATUS[0]} ${pipestatus[1]} # exit code of ls via bash or zsh
    fi
    ls -l "$@"
  }
fi

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
function PSWD() {
  local p="$*" space A B cols="${COLUMNS:-`tput cols 2>/dev/null || echo 80`}"
  p="${p/$HOME/\~}"         # shrink home down to a tilde
  if [ -d /cygdrive ] && [ "${p#/cygdrive/?/}" != "$p" ]; then
    p="${p:10:1}:${p:11}"   # /cygdrive/c/hi -> c:/hi
  fi
  space="$((${#USER}+${#HOSTNAME}+6))"  # width w/out the path
  if [ "$cols" -lt 60 ]; then echo -n "$N "; space=-29; p="$p$N\b"; fi
  if [ "$cols" -lt "$((space+${#p}+20))" ]; then # < 20 chars for the command
    A=$(( (cols-20-space)/4 ))      # a quarter of the space (-20 for cmd)
    if [ $A -lt 4 ]; then A=4; fi   # 4+ chars from beginning
    B=$(( cols-20-space-A*2 ))      # half (plus rounding) of the space
    if [ $B -lt 8 ]; then B=8; fi   # 8+ chars from end
    p="${p:0:$A}..${p: -$B}"
  fi
  echo "$p"
}

PSC() { printf $'\[\e[%sm\]' "${*:-0;0}"; }
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:
867,562

Related videos on Youtube

Mark Norgren
Author by

Mark Norgren

Updated on September 17, 2022

Comments

  • Mark Norgren
    Mark Norgren over 1 year

    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 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 macOS X, 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, I 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 use 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.

    • Admin
      Admin over 9 years
      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
    • Admin
      Admin over 6 years
      Did anybody see a tool to color columns? That is a column -t --color?
    • Admin
      Admin over 2 years
      @TomášPospíšek have you looked into grc ?
    • Admin
      Admin over 2 years
      thanks for the pointer @amrx
  • tsvallender
    tsvallender almost 14 years
    Or if you want to use ZSH, Phil Gold's prompt at aperiodic.net/phil/prompt is a work of art.
  • manatwork
    manatwork over 12 years
    Please specify your shell. The question's only shell specific tag is bash, but I feel your code is not bash.
  • Mischa Arefiev
    Mischa Arefiev over 12 years
    @manatwork: sorry, forgot to mention that it was Zsh. Updated my post.
  • Xander Dunn
    Xander Dunn over 11 years
    See here for the solution to a line problem I got when I used the above PS1: stackoverflow.com/questions/5087036/…
  • sophie668
    sophie668 almost 11 years
    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.
  • Kris
    Kris over 9 years
    I've updated the answer to reflect the escaped brackets for the colors in the prompt. Thanks!
  • Adam Katz
    Adam Katz over 9 years
    $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
    Adam Katz over 9 years
    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.
  • Sygo
    Sygo over 9 years
    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.
  • Adam Katz
    Adam Katz over 9 years
    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).
  • Sygo
    Sygo over 9 years
    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...
  • mattts
    mattts about 9 years
    Colors are available for ls on OS X, but it is done by using export CLICOLOR=1.
  • Admin
    Admin almost 8 years
    If I could, I would downvote this for the Oh-My-ZSH suggestion. As a systems engineer who works extensively in the Terminal, and as somebody who tried to adopt zsh/oh-my-zsh into my workflow, I can honestly say I would never recommend ZSH to anyody. Sure, you can symlink zsh to a file named after any other shell and emulate that shell, but when you do that it doesn't read your .bashrc, .bash_profile, etc. Also, you cannot put emulate bash in your .zprofile or .zshrc files. For anybody who works with advanced features in BASH, there are many subtleties that will bite you. BASH is a better sh.
  • Admin
    Admin almost 8 years
    The only thing that ZSH has out of the box that is better than BASH is command completion, but even that is programmable in BASH. Maybe somebody who doesn't use the shell except for occasional mundane tasks should adopt ZSH, but it's not for anybody who needs to use the shell extensively. the =~ operator can bite you, the way ZSH handles arrays can bite you, etc. After using ZSH/Oh-My-ZSH for about 9 months I had enough of it. I was using a custom theme that I wrote myself, I ported it to BASH and wrote my own git promptline and I've never looked back. Now I no longer worry about portability
  • Admin
    Admin over 7 years
    "it has one of the most powerfull console features that I saw. One of them is picking theme for your terminal."
  • JdeBP
    JdeBP over 7 years
    Nonetheless, ThomasW is correct to point out that the answer is erroneous in saying that colours are not available with ls on MacOS 10. The answer is also erroneous in that the prompt strings here are in fact faulty. They do not correctly balance \[ and \], and have caused problems for at least one person copying this answer.
  • Steven Almeroth
    Steven Almeroth over 7 years
    grep: warning: GREP_OPTIONS is deprecated; please use an alias or script
  • Green
    Green almost 7 years
    A screenshot would be nice
  • Adam Katz
    Adam Katz over 6 years
    Update on $LSCOLORS GNU parity: LSCOLORS=ExGxFxDaCxDaDaxbxDacad.
  • Adam Katz
    Adam Katz over 6 years
    My PSWD() function used to be POSIX-compatible but it's so much easier facilitated using bash/zsh substring handling. See revision 6 for the POSIX version, which involves lots of question marks and wasn't at all adaptable to terminal width. I didn't update the screenshot, but it's only a slight change at the 80 character width.
  • GKFX
    GKFX over 6 years
    Your values are the same for COLOR_BLACK and COLOR_GREY.
  • Artur Vieira
    Artur Vieira over 6 years
    Hello, how do you make the flags, for the prompt path? I am mentioning the rectangular bars with triangle ends Thanks
  • Spencer D
    Spencer D over 6 years
    Any fork or alternative links for the vcprompt? Seems like it's now a 404.
  • Ben
    Ben about 6 years
    does it work in a ubuntu gnu terminal as well?
  • Cyril Chaboisseau
    Cyril Chaboisseau almost 6 years
    lnav is also a great tool to show colorized logfiles
  • Admin
    Admin almost 6 years
    @JonathanHartley, your comment looks like you left it incomplete. ?
  • Admin
    Admin almost 6 years
    Thank you for your concern but my comment says everything I intended to say.
  • Kris
    Kris over 5 years
    Added a new link to the source for vcprompt as a GitHub gist, and a screen capture of the colorized final prompt.
  • Gert van den Berg
    Gert van den Berg over 5 years
    When using links to external source, you should check the "Provide context for links" part (Quote important parts) of the relevant part of the guide: unix.stackexchange.com/help/how-to-answer
  • Simon C.
    Simon C. over 5 years
    The ls --color=always doesn't work. @Michael Durrant' s approach is better for this: ls --color=al > /dev/null 2>&1 && alias ls='ls -F --color=al' || alias ls='ls -G'
  • Simon C.
    Simon C. over 5 years
    CLICOLOR=1 doesn't work for me with FREEBSD 11.2
  • Adam Katz
    Adam Katz over 5 years
    @SimonC. – You might be using GNU utilities on your FreeBSD system rather than the BSD ones. CLICOLOR=1 ls should do the same thing as ls -G using BSD (ls -g on older BSDs). If ls --color works (no error), you're using GNU's ls command and $CLICOLOR is ignored.
  • Simon C.
    Simon C. over 5 years
    Thanks. It's really strange then. Putting CLICOLOR=1 in my bashrc doesn't do anything, though when doing echo $CLICOLOR it tells me it's at when. While defining CLICOLOR=1 just before calling ls as you mentioned in your post works. and ls --color return an "illegal option", suggesting I am indeed using BSD ls... not sure what's happening
  • Adam Katz
    Adam Katz over 5 years
    @SimonC. – You have to actually load your ~/.bashrc for any changes to take effect. Either run source ~/.bashrc or start a new bash session (launch a terminal or run bash).
  • Simon C.
    Simon C. over 5 years
    yes yes I know and did (both things, starting bash again as well as source the rc file from within bash),you can see here, on my side I dont know what I am doing wrong :imgur.com/a/RVkUple
  • Adam Katz
    Adam Katz over 5 years
    Maybe try running export CLICOLOR after you define it. If that works, I'll add it to my answer.
  • Teemu Leisti
    Teemu Leisti about 5 years
    The .bashrc example is missing the final fi, and could be converted to a single-line command: type colordiff &> /dev/null && alias diff='colordiff'
  • amiabl
    amiabl almost 5 years
    You may need to source the .bashrc file for the modification to be effective. You can do it with the following command. source /path/to/.bashrc
  • RadaRK
    RadaRK over 2 years
    Use the colors before the parts you want to color. This is where i found this gist.github.com/vratiu/9780109