1. Overview

The Bash shell is the default shell in many popular Linux distributions. In our daily routine, when we open a terminal, we see that the Bash shell prints a command prompt. The prompt indicates that the shell is ready to process the next command we may enter.

The command prompt has a predefined format. Most of the time, this format contains information like the hostname, the username, or the working directory.

In this tutorial, we’ll examine ways to customize the Bash shell’s command prompt.

2. The PS1 Shell Variable

The PS1 shell variable defines the text printed before the blinking cursor in our terminal. We may set a simple value like a single character, for example, $ or #. On the other hand, we may set complex expressions that are evaluated when the prompt is printed.

Note that our changes are not permanent when we set a value directly to the PS1 shell variable through the command-line interface. In other words, if we log out and log in again, the shell initializes the PS1 variable to its default value.

2.1. Setting the PS1 Shell Variable

We may assign a value to the PS1 shell variable, like any other shell variable:

ubuntu@speedy-courser:~$ PS1="$ "
$

Note that any change in the PS1 variable is reflected immediately to the command prompt. In this example, we set our prompt to the dollar sign and a space character inside double-quotes. We add a space character to ensure that our commands are separated from the prompt. This improves readability.

2.2. Printing the PS1 Shell Variable

We can print the value of the PS1 shell variable with the echo command:

ubuntu@speedy-courser:~$ echo $PS1
\u@\h:\w$ 
ubuntu@speedy-courser:~$

As a result, the echo command prints the expression stored in the PS1 variable. Note that the double quotes are not printed. Also, note the dollar sign used to refer to the PS1 variable.

3. Escape Characters

There’s a list of predefined escape characters with special decoding. These characters are preceded by the backslash character. Some examples are:

  • \d: The current date
  • \t: The current time
  • \h: The hostname of our Linux machine
  • \u: The username of the logged-in user
  • \w: The user’s working directory
  • \[: Beginning of a sequence of non-printable characters that somehow control the behavior of the terminal
  • \]: End of non-printable control characters sequence

We can use these special characters to create expressions to set the PS1 variable:

$ PS1="\u@\h:\w$ "
ubuntu@speedy-courser:~$

As a result, we set our prompt to display the username, the hostname, and the working directory.

4. Using Commands

Except for escape characters, we may incorporate shell commands in the expression we set to the PS1 shell variable. The commands should be nested in the command substitution operators. These operators are $(…) or `…`.

To avoid command substitution when we assign our expression to the PS1 shell variable, we may have to escape the $ sign with a backslash character. Let’s try to create a similar command prompt to the one we’ve created in the previous section:

$ PS1="$(whoami)@$(hostname):$(pwd):\$(date) "
ubuntu@aspiring-grub:/home/ubuntu:Tue Jun 14 16:07:51 EEST 2022

As a result, we set our prompt to contain the username, the hostname, the working directory, and the current date. Most importantly, notice the escape character in the dollar sign of the date command. This forces the substitution of the date command every time the prompt is printed.

5. Foreground Colors

We set terminal colors with non-printable escape character sequences. *A color character sequence starts with a \[\033[ or \[e[, and ends with a \].* In addition, it should contain a code to a corresponding color.

Color codes comprise two parts, separated by a semicolon, and are followed by the letter m. The first part is the zero number for the dark version of the color or one for the light version. The second part defines the color. Moreover, all codes that set the font color start with digit 3. Let’s change the color of our command prompt to green:

$ PS1="\[\033[0;32m\]\d:\t$ \[\033[0m\]"
Tue Jun 14:16:45:35$

In the above example, we’ve created a green color prompt that displays the current date and the dollar sign with a space after it. The code for the green color is 0;32m. Also, keep in mind that we terminate the green color with the character sequence \[\033[0m\]. Otherwise, the green color will stay, having our commands and their output colored in green.

6. Background Color

We can also set the background to green:

$ PS1="\[\033[0;42m\]\d:\t$ \[\033[0m\]"
Tue Jun 14:22:55:12$

The code 0;42m sets the background color of the command prompt background to green. Color codes that start with digit 4 define the background color.

7. Underline

We can add the 4m code to underline the prompt. In addition, we can include multiple codes together to combine background, foreground, and underline settings:

$ PS1="\[\033[1;33;42;4m\]\d:\t$ \[\033[0m\]"
Tue Jun 14:23:45:35$

As a result, the command prompt is displayed underlined in the green background and yellow font.

8. Cursor Movement

Escape characters along with the tput command enable us to set the cursor position. It’s a powerful feature that helps us to further customize the command prompt. In addition, we can use it to build text-based user interfaces in the terminal.

8.1. Setting the Cursor Position

We can set the cursor position with the \[\033[;H escape sequence that moves the cursor to the coordinates (L, C). Let’s move the cursor to line 1 and column 1 of the terminal:

$ PS1="\[\033[1;1H\]"

Move terminal cursor to the first line and column

We may notice that the cursor stays permanently in this position. To continue working with our terminal, we can set another value to the PS1 variable.

8.2. Saving and Restoring the Cursor Position

Saving the current cursor position and restoring the cursor to the last saved position is a convenient capability of the Bash shell. We can save and restore the cursor position with the tput command. The tput sc command saves the current cursor position. In addition, the tput rc command restores the cursor to the last saved position.

8.3. Printing Date in the Upper Right Corner

Let’s put them all together and create a command prompt that prints the date in the upper right corner of the terminal:

PS1="\$(tput sc)\[\033[1;\$(echo -n \$((\$COLUMNS-15)))H\]\d\$(tput rc)$ "

Display date to upper right corner

Many things happen in the above expression. Firstly we save the current cursor position with the tput sc command. Note that the tput sc command is nested in the command substitution operator $(…). Secondly, we move the cursor to the upper-right position of our terminal.

Therefore, we set the cursor line number to 1 and create an expression to calculate the column number. In this expression, we get the last column number of our terminal from the environment variable $COLUMNS, and we subtract 15 to create the space necessary to print the date.

After setting the cursor position to the upper-right corner, we print the current date with the \d escape character. However, we still haven’t printed anything to the command prompt text. To do this, we first restore the cursor position to its initial position with the tput rc command and print the dollar sign.

9. Setting the Terminal Window Title

Changing the terminal window title is an interesting customization. We can define a new title in the PS1 shell variable between the escape characters \[\033]0; and \a\]:

$ PS1="\[\033]0;Hello World of Linux\a\]$ "

Set title to terminal window

Here, we set the terminal window title to the string Hello World of Linux. Moreover, we set the primary command prompt to the dollar sign. Do note that this customization may not work on all terminals. It is expected to work on XTerm terminals. To check the type of our terminal, we can use the $TERM shell variable.

10. Other Shell Variables

Although PS1 is the most important variable we use to customize the command prompt, there are additional variables affecting other aspects of our terminal. There are six PS shell variables in total, starting from PS0 and reaching PS5. Besides the PS1 variable, the PS2 variable is interesting. The rest of the PS variables are rarely displayed to the majority of users.

10.1. The PS2 Shell Variable

The PS2 shell variable is the secondary prompt printed when a command spans multiple lines. We set it and print it similarly as we did with the PS1 shell variable:

$ echo $PS2
>

As a result, the > character is printed. We may change it by assigning a different value to the PS2 variable:

$ PS2="=>"
$

Here, we set the PS2 variable to the => string. To test it, we can simply write:

$ echo "Hello world of \
=>Linux"
Hello world of Linux

So, we’ve successfully changed the secondary command prompt from the > character to the => string.

10.2. The PROMPT_COMMAND Environment Variable

The Bash shell evaluates the PROMPT_COMMAND variable contents just before it prints the primary command prompt. This could be useful for further customization of the PS1 variable. The variable accepts regular Bash shell commands:

$ PROMPT_COMMAND=pwd
/home/ubuntu
$

Here, we set the PROMPT_COMMAND variable to the pwd command. As a result, the Bash shell prints the working directory before the command prompt.

11. The tput Command

Until now, we’ve mainly used escape characters to change colors or set the cursor position. Escape characters may complicate expressions, and they may be hard to remember. An alternative way of achieving similar results is the tput command.

The tput command uses an internal database called the terminfo database, which documents the terminal capabilities of our Linux machine and their corresponding escape sequences. Furthermore, we can print the terminfo database with the infocmp command:

$ infocmp | grep setaf
        setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,

In the above example, we have reduced the output of the infocmp command for brevity reasons using the grep command. We print only the record that deals with the setaf capability. We can use the setaf capability to set the foreground color:

$ tput setaf 2
$

Color codes lie in the 0 to 7 code range. Code number 2 corresponds to the color green. In a similar way, we can change the background color of our terminal window with the tput setab command.

12. Making Changes Persistent

We can make our customizations persistent by saving them to the .bashrc script file. This file lies in the user’s home directory. Our Linux machine executes this script when we log in. We can view this file with our favorite editor. Note that this file sets the PS1 shell variable to a default value. Consequently, we can customize our command prompt by editing the .bashrc file:

$ echo PS1='\\u:\\h$ ' >> .bashrc
$ source .bashrc
ubuntu:aspiring-grub$

Here, we appended a line of code that sets the PS1 variable to display the current user and the hostname. Next, we used the source command to reload the .bashrc file. The source command executes all the commands interactively in the .bashrc script.

As a result, we observe the modified primary prompt, which is persistent even if we log out and log in again. To restore the default appearance of our command prompt, we can open the .bashrc script with our favorite editor and delete the appended line.

13. Creating Complex Prompts

As we have already seen, customizing the command prompt deals with shell variables, escape characters, and commands. This leads to the creation of complex expressions that we may find hard to manage and comprehend.

In addition, we may want to save our custom command prompt code for future use. Therefore, an approach for creating complex prompts might be to create shell scripts with functions that encapsulate our command prompt customization code.

13.1. Functions

Inside a bash shell script file, a function is declared with the keyword function. For example, we can create a new file with the name customprompt and a new function customp:

function customp {
    GREEN="\[$(tput setaf 2)\]"
    WHITE="\[$(tput setaf 7)\]"
    PS1="$GREEN \$ $WHITE "
}

First, inside the function body, we set the foreground color to green with the tput command. Then, we set the primary command prompt to the dollar sign. Last, we set the foreground color to white. Note that the code for setting the color is assigned to the variables GREEN and WHITE, thus making the code more readable.

13.2. Sourcing and Execution

Following the creation of the script file, we source the script and execute the function from the command line:

ubuntu@aspiring-grub:~$ source customprompt
ubuntu@aspiring-grub:~$ customp
$

As a result, we have turned our command prompt to the green dollar sign.

14. Conclusion

In this article, we examined some bash shell customizations. Common customizations include setting the primary command prompt, changing the foreground and the background color, as well as changing the position of the cursor in the terminal. In conclusion, the Bash shell offers powerful mechanisms for customization that enable us to create interesting text-based user interfaces.