May 8, 2014

How to Make a Fancy and Useful Bash Prompt in Linux

We can program our humble Bash prompt to display all kinds of useful information, and pretty it up as well. We're sitting there staring at our computers all day long, so why not make it look nice? We will learn how to quickly test new configurations and quickly reverse them, how to make nice colors, how to display different types of information, customize it for different users, and make a multi-line prompt.

Configuring a different prompt for SSH sessions is one of my favorites, because it has saved me from many an error due to running a command in the wrong terminal. A dull life without broken servers is not too much to ask. Just add these lines to the ~/.bashrc of your user on the remote machine:

if [ -n "$SSH_CLIENT" ]; then text=" ssh-session"
export PS1='\[\e[1;32m\]\u@\h:\w${text}$\[\e[m\] '

Then load your changes without logging out:

$ source ~/.bashrc

Now open an SSH session from another machine and you will see something like figure 1.

fig-1 green ssh prompt

You can even do all of this over SSH so you don't have to get up.


Of course you may choose from a multitude of splendid ANSI colors. You can find ANSI color code charts all over the place. These are the basic colors:

0;30m   Black
0;31m   Red
0;32m   Green
0;33m   Yellow
0;34m   Blue
0;35m   Purple
0;36m   Cyan
0;37m   White

0 is normal font. Change the 0 to 1 for bold, 4 for underline, and 5 for slow blink. In the SSH example text=" ssh-session" is whatever text string you want, and the text label is also arbitrary, as long as it matches ${text}.

The Bash shell supports a lot of special characters for customizing the prompt. For example, \u is the username, and \h is the hostname. Other useful special characters are:

\d : the date in "Weekday Month Date" format 
\t : the current time in 24-hour HH:MM:SS format
\w : the current working directory
\s : the name of the shell
\n : newline
\[ : begin a sequence of non-printing characters, for embedding a terminal control sequence into the prompt
\] : end a sequence of non-printing characters

Your custom prompt sequences are hard to read because of all the escapes, but you'll get the hang of it with a little practice. Note how the whole sequence is enclosed in single quotes, and it starts after PS1=. \u@\h: is an example of how to insert punctuation marks after the special characters. Literal punctuation marks are not escaped. You can insert spaces in the same manner; for example, see the closing color code, \[\e[m\] ', which has a space after last square bracket. This creates a space after the dollar sign. This example also shows how to reset the font color back to the terminal default. In the next example you'll see how to set a custom font color on right side of the prompt.

This example creates a pleasant cyan prompt with date and time (figure 2). Note also how you can add square brackets around the prompt, or any part of it, by enclosing the special characters with un-escaped brackets:

$ PS1='\[\e[1;34m\][\d \t \u@\h \w]\$\[\e[m\] '

fig-2 cyan prompt

You can go nuts with colors (figure 3):

$ PS1='\[\e[1;36m\]\d \[\e[1;32m\]\t \[\e[1;33m\]\u@\[\e[1;35m\]\h:\w\$\[\e[0;31m\] '


Putting a color code at the end, like \[\e[0;31m\], sets a custom color on anything you type, and everything else that appears after the prompt.

Multi-line Prompt

Most terminals are 80 characters wide, so you run out of room when you have a long prompt. So why not break up the lines? You can with our old friend the newline special character, \n:

PS1='\[\e[1;33m\]\u@\h \w ->\n\[\e[1;36m\] \@ \d\$\[\e[m\] '

This creates a nice prompt with the username, current directory, and time and date (figure 4). It has an arrow to indicate there is another line, and it terminates in a proper dollar sign for an unprivileged user.

fig-4 multiline

Root Prompt

The root prompt is indicated by the hash mark, #. As long as we're making fancy prompts, why not make one for the root user too? Add these lines to both your ~/.bashrc, and to root's/root/.bashrc:

if [ $(id -u) -eq 0 ];
    PS1='\[\e[1;36m\][\d \t \u@\h \w]\$\[\e[m\] '
    PS1='\[\e[1;33m\][\d \t \u@\h \w]\$\[\e[m\] '

You can either sudo or su to root, then source ~/.bashrc, and enjoy root's new fancy prompt. You can fancy up root's prompt just like for any user. A quick way to check any user's ID number is with the ID command:

$ id -u

Put a Fortune in your Prompt

Remember way back when we did Put a Talking Cow in Your Linux Message of the Day? You can also put one in your Bash prompt by adding this line to ~/.bashrc::

[[ "$PS1" [[ && /usr/games/fortune | /usr/games/cowsay -n


~/.bashrc Gotchas

If there is not a ~/.bashrc then create one. On most distros it is sourced from ~/.profile, which you can verify by looking for something like these lines in ~/.profile:

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
	. "$HOME/.bashrc"

If your particular flavor of Linux does not use ~/.profile, then look for ~/.bash_profile or ~/.bash_login. If it doesn't have those then you have a weird Linux, and must consult your distro documentation to find out what to do.

Feeling lost? You can output your current prompt settings:

$ echo $PS1 

There are something like a billion and twelve ways to mess with your Bash prompt, so visit the Bash Reference Manual to learn all about it.

Click Here!