Mar 2007

Colors & Prompts in BASH

Bourne Again Shell offers a lot of power, flexibility and fun. Many new Unix users do not realize the flexibility of the shell environment; indeed; many new Unix users regard the shell as primitive and too restricted: nothing could be further from the truth. With very little time investment a new Unix user can learn how not to just make their work environment in the shell more productive but even a little fun.

This text only discusses the bash shell and the latest versions of the bash shell.

In the old days (a few years ago...) shell prompts did not all act alike. Most earlier Unix shells did not react well to path munging, prompt changing or special characters. The modern Bash shell does not suffer issues like long path name buffer mangling, getting lost or not having enough built ins.

The Prompt

First and foremost to (most) users the shell prompt itself; there are 3 approaches to the shell prompt (in no particular order) for those who want to customize it:

  • Put pwd in the prompt (do not care about the rest).
  • A very sexy/l33t prompt (do not care about the rest).
  • A nice prompt and pwd crammed in there.

Addressing each point is easiest...

PWD

The basic method of changing a prompt is by modifying the PS1 variable:

[mui@vela:~]$ PS1="foo% "
foo% 

Bash has a builtin for handling the current working directory:

\w

On most Linux systems the current or print working directory sequence is already defined in /etc/profile:

[mui@vela:~]$ PS1="foo% "
foo% PS1="foo \w $"
foo ~ $cd docs
foo ~/docs $

So there is the pwd capability, now onto what can be done with the prompt string itself.

Pretty Prompts

By default, Bash prints whoami at (&) hostname if there is a default profile installed for Bash on the particular system. Bash uses some more built in sequences to do so:

if [ $PS1 ]; then
  if [ "$BASH" ]; then
    PS1='\u@\h:\w\$ '
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

Specifically, the \u and \h set the user and hostname. What most folks like, however, is to use interesting looking characters in the prompt. This is none to difficult to do:

PS1=":-) \h\w$ "
:-) vela~/www/systhread.net/texts$ 

File Colors

Colors in the shell are controlled by codes. Files and the prompt can be colorized, however, they are done differently. Files are colored by using ls --color which can be aliased as ls=`ls --color'. The default location of file color schemes varies from system to system. To use individual colors first build a file (or copy the default one) and put it in $HOME/.dir_colors. Following is an example dircolors file:

COLOR tty
OPTIONS -F -T 0
# Below, there should be one TERM entry for each termtype that is colorizable
TERM linux
TERM console
TERM con132x25
TERM con132x30
TERM con132x43
TERM con132x60
TERM con80x25
TERM con80x28
TERM con80x30
TERM con80x43
TERM con80x50
TERM con80x60
TERM cons25
TERM xterm
TERM rxvt
TERM xterm-color
TERM color-xterm
TERM vt100
TERM dtterm
TERM color_xterm
TERM ansi
TERM screen
TERM screen.linux
TERM kon
TERM kterm
TERM gnome
TERM konsole

EIGHTBIT 1

# 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   # global default, although everything should be something.
FILE 00     # normal file
DIR 00;36   # directory
LINK 00;35  # symbolic link
FIFO 40;33  # pipe
SOCK 01;35  # socket
BLK 40;32;00    # block device driver
CHR 40;32;00    # character device driver
ORPHAN 01;05;37;41  # orphaned syminks
MISSING 01;05;37;41 # ... and the files they point to
# This is for files with execute permission:
EXEC 00;33

# List any file extensions like '.gz' or '.tar' that you would like ls
# to colorize below. Put the extension, a space, and the color init string.
# (and any comments you want to add after a '#')
.cmd 00;32 # executables (bright green)
.exe 00;32
.com 00;32
.btm 00;32
.bat 00;32
.sh  00;32
.csh 00;32
.tar 00;31 # archives or compressed (bright red)
.tgz 00;31
.arj 00;31
.taz 00;31
.lzh 00;31
.zip 00;31
.z   00;31
.Z   00;31
.gz  00;31
.bz2 00;31
.bz  00;31
.tz  00;31
.rpm 00;31
.cpio 00;31
.jpg 00;35 # image formats
.gif 00;35
.bmp 00;35
.xbm 00;35
.xpm 00;35
.png 00;35
.tif 00;35

To change a color, simply use the color values desired. Using the colors requires an eval statement in a login file, for instance the $HOME/.bashrc:

eval `dircolors $HOME/.dir_colors`

Colorized Prompt

Colorizing the prompt is similar. The Bashish provides a good start for the bits needed in $HOME/.bashrc:

DULL=0
BRIGHT=1

FG_BLACK=30
FG_RED=31
FG_GREEN=32
FG_YELLOW=33
FG_BLUE=34
FG_VIOLET=35
FG_CYAN=36
FG_WHITE=37

FG_NULL=00

BG_BLACK=40
BG_RED=41
BG_GREEN=42
BG_YELLOW=43
BG_BLUE=44
BG_VIOLET=45
BG_CYAN=46
BG_WHITE=47

BG_NULL=00

##
# ANSI Escape Commands
##
ESC="\033"
NORMAL="\[$ESC[m\]"
RESET="\[$ESC[${DULL};${FG_WHITE};${BG_NULL}m\]"

##
# Shortcuts for Colored Text ( Bright and FG Only )
##

# DULL TEXT

BLACK="\[$ESC[${DULL};${FG_BLACK}m\]"
RED="\[$ESC[${DULL};${FG_RED}m\]"
GREEN="\[$ESC[${DULL};${FG_GREEN}m\]"
YELLOW="\[$ESC[${DULL};${FG_YELLOW}m\]"
BLUE="\[$ESC[${DULL};${FG_BLUE}m\]"
VIOLET="\[$ESC[${DULL};${FG_VIOLET}m\]"
CYAN="\[$ESC[${DULL};${FG_CYAN}m\]"
WHITE="\[$ESC[${DULL};${FG_WHITE}m\]"

# BRIGHT TEXT
BRIGHT_BLACK="\[$ESC[${BRIGHT};${FG_BLACK}m\]"
BRIGHT_RED="\[$ESC[${BRIGHT};${FG_RED}m\]"
BRIGHT_GREEN="\[$ESC[${BRIGHT};${FG_GREEN}m\]"
BRIGHT_YELLOW="\[$ESC[${BRIGHT};${FG_YELLOW}m\]"
BRIGHT_BLUE="\[$ESC[${BRIGHT};${FG_BLUE}m\]"
BRIGHT_VIOLET="\[$ESC[${BRIGHT};${FG_VIOLET}m\]"
BRIGHT_CYAN="\[$ESC[${BRIGHT};${FG_CYAN}m\]"
BRIGHT_WHITE="\[$ESC[${BRIGHT};${FG_WHITE}m\]"

# REV TEXT as an example
REV_CYAN="\[$ESC[${DULL};${BG_WHITE};${BG_CYAN}m\]"
REV_RED="\[$ESC[${DULL};${FG_YELLOW}; ${BG_RED}m\]"

PROMPT_COMMAND='export ERR=$?'

To create a colorized prompt use the color names in the prompt where desired:

PS1="${BRIGHT_CYAN}[${CYAN}\u$@\h${WHITE}:\w${BRIGHT_CYAN}]${NORMAL}\$ ${RESET}"

Simple, functional and just a little fun.

Sources