*[@slhck](http://superuser.com/users/48078/slhck) provided valuable suggestions and proof-read most of this. Thanks Werner!*

[![Username](http://superuser.com/users/flair/22317.png)](http://superuser.com/users/22317)

# Customizing Your Bash Command Prompt

When you're working on your Linux or Mac OS X system's command line, the prompt is the text to the left of the commands you enter. The default prompt varies for every system, but it usually gives you an indication of your username, your machine's host name and your current working directory. Also, it ends with a dollar sign `$` if you're working as a normal user. If you're working with `root` privileges, it ends with `#` instead.

The prompt can be customized to include relevant information that can help you increase productivity, to hide information you don't care about, or to highlight the lines in your terminal output where you entered commands.

This post will show how to customize your `bash` prompt, and, in the process, explain a few of its more advanced features that improve your productivity. [Bash](http://www.gnu.org/s/bash/) is the default shell on Mac OS X, available for all (or most) Linux distributions, if not already included, and available on Windows via [Cygwin](http://www.cygwin.com/).

![Continue Reading…](https://i.sstatic.net/XpnxH.png)

---

Bash primarily uses two variables that define how your prompt looks like: `PS1` specifies the format of your regular prompt, while `PS2` defines the continuation prompt: It appears when you enter a line ending with a backslash `\` to continue input on the next line. In the following example, I split the `ls` command over two input lines:

    Saurus:~ danielbeck$ l\  
    > s  
    Desktop		Documents	Downloads	Library		Movies		Music		Pictures	Public		Sites
    Saurus:~ danielbeck$ _

<sup>In this post's monospaced example sections, an underscore will represent the cursor position when showing examples of a prompt, while a single `$` character represents a generic prompt, except where otherwise noted.</sup>

As you can see, my `PS1` prompt contains the host name (*Saurus*), the current working directory (`~` is a synonym to the user's home directory), my username (*danielbeck*), and an indicator that I am a regular user (`$`).

The second line is my default continuation prompt: A greater-than sign, followed by a single space.

You can assign different values to your prompt right in your shell session, as shown below. The values you set this way will be reset once you close your session, so you can experiment freely with the examples in this post. Just restart your shell session to reset the prompt variables to your permanent default values.

    Saurus:~ danielbeck$ PS1='my new prompt $ '
    my new prompt $ _

To display the currently assigned values (e.g. for copying them to your bash configuration files), you can `echo` these variables. The second line in the following example is the output of the command on the first line, the prompt is repeated after execution on the third line:

    my new prompt $ echo $PS1
    my new prompt $
    my new prompt $ _

Once you start adding shell scripts and program invocations to your prompt (see *Executing scripts and programs* below), this will already contain evaluated expressions, so you should not rely on this alone.

## Displaying additional information ##

Bash supports several placeholder sequences for certain kinds of information that are commonly displayed in a prompt. These take the format of a backslash `\`, followed usually by a single character. Of course, you can find a [list of all possible placeholders](http://www.gnu.org/s/bash/manual/bash.html#Printing-a-Prompt) in the bash manual. To re-create the default prompt shown above, one would enter the following:

     $ PS1='\h:\W \u\$'

This prompt contains the host name, followed by a colon, followed by the current working directory, a space character, the user name, and the prompt indicator. As already mentioned above, it is a hash character `#` if the user has `root` privileges, and a dollar character `$` otherwise.

In [this question](http://superuser.com/questions/290638/making-linux-shell-prompt-show-last-return-value), [Xenorose](http://superuser.com/users/2765/xenorose) asked:

> I'm currently on a Linux machine and the shell prompt is showing me the […] number of executed commands. My own computer doesn't have this, how can I configure it?

The answer is the placeholder sequence `\#`: It prints the command number of the command following it. The first command of a bash session starts at 1, and every subsequent command increases it by 1. In the following example, `PS1='\# \$ '`:

    Last login: Thu Aug 25 21:54:14 on ttys001
    1 $ pwd
    /Users/danielbeck
    2 $ pwd
    /Users/danielbeck
    3 $ pwd
    /Users/danielbeck
    4 $ _


A very similar sequence is `\!` which represents the *history number* of the command following it. You can execute the command on that line again by entering an exclamation mark, followed by that command's *history number*.

    $ PS1='\! $ '
    1478 $ pwd
    /Users/danielbeck
    1479 $ cd /
    1480 $ !1478
    pwd
    /
    1481 $ _

As you can see, the command executed through history expansion of `!1478` is printed again (`pwd`), and then executed, this time with different results.

Once your prompt grows in length, you might want to add a line break or two to it by adding `\n` at the appropriate positions.

## Colors ##

The prompt, or parts of it, can also be a different color than the default. Doing this is a bit tricky though. There are another few special sequences used for this. Similar to HTML or other document markup languages, the highlighted parts are enclosed in a pair of special formatting sequences. For HTML, this would be the `<span>` and `</span>` tag pair. In bash, it looks like this:

    regular text \[\033[0;32m\] green text \[\033[m\] regular text again

The actual formatting code is enclosed, similar to angle brackets for HTML tags. `\[` and `\]` are special sequences that indicate non-printing sequences, so bash can ignore everything between them for length calculations (e.g. when wrapping output lines depending on the terminal width). Strictly speaking, they're optional, but you don't want to mess up your terminal's line breaking behavior by skipping them.

`\033` is another special sequence: The digits are octal and represent the [ASCII](http://en.wikipedia.org/wiki/ASCII) character with the corresponding code, in this case *Escape*. It starts a terminal control escape sequence (`\033[…m`) specifying font and color attributes. For a list of such escape sequences, see [this web page](http://www.termsys.demon.co.uk/vtansi.htm).

We use two such sequences:

* `\033[0;32m` resets text formatting and makes the following output a regular green
* `\033[m` is an "empty" sequence containing no formatting rules. It resets output formatting to its defaults.

[This page](http://networking.ringofsaturn.com/Unix/Bash-prompts.php) provides a nice `PS1` (at the bottom) so you can see all colors and other formatting options as part of a single `PS1`. Just be prepared to endure blinking text, if your terminal emulator can handle it.

Through some `bash` debugging facilities, it's even possible to add these formatting rules to the [commands you enter](http://superuser.com/questions/204003/make-os-x-terminal-commands-i-type-bold).

## Executing scripts and programs ##

You can execute arbitrary CLI programs as part of displaying your prompt, adding their output to it. For example, you might not like the behavior of `\W` to print `~` instead of the full path to your home directory. No problem, just run `pwd`, enclosed in `$( )`, instead:

    Saurus:~ danielbeck$ PS1='\h:$( pwd ) \u\$ '
    Saurus:/Users/danielbeck danielbeck$ _

We usually have a choice of enclosing strings in single or double quotation marks. Since `bash` evaluates all expressions enclosed in `$(…)`, like `$( pwd )` here, as well as variables (e.g. `$PS1`), when enclosed in double quotation marks, we need to make sure to put values assigned to `PS1` in single quotation marks now. It didn't make a difference earlier, but we want these commands to be evaluated every time `PS1` is printed by the shell, not just once when the value is assigned to `PS1`. Just remember to always use single quotation marks and you won't run into this problem.

---

In my experience, it's sometimes easy to overlook non-zero return codes of more complex commands with many lines of output. To make sure I notice these possible errors, I can add the previous command's return code to my prompt, like with the following `PS1`:

    PS1='$( RET=$?; if [ $RET != 0 ] ; then echo "rc: $RET"; fi )\n\$ '

As a side effect, your prompt will now always start with a blank line if the previous command returned `0`. While you can add line breaks to your prompt by using the sequence `\n`, `bash` discards all other newlines that are a result of e.g. multi-line program return values.

If you want to have a multi-line output depending on some conditions, you need to put that part of your prompt into the variable `PROMPT_COMMAND`. It is expected to contain a script that is executed just before `PS1` is printed. To continue with the previous example of program return codes, use the following:

    PROMPT_COMMAND='RET=$?; if [ $RET != 0 ] ; then echo "rc: $RET"; fi'
    PS1='\$ '

This produces almost the same results as the previous example, except that executing programs with exit code 0 won't print an additional blank line now.

To reset `PROMPT_COMMAND` again, you can assign it an empty value:

    PROMPT_COMMAND=

## Complete example ##

The following prompt is an example on how you could combine the various elements I mentioned above into a powerful and informative prompt. I've been using this prompt, or slight variations of it, for a few months now.

> `PS1='\[\033[0;32m\]\u\[\033[00m\] in \[\033[0;32m\]$( pwd ) ($( OUT=$( ls -A | wc -l ); echo $OUT ) entries, $(( $( ls -A | wc -l ) - $( ls | wc -l ) )) hidden)\n\[\033[1;32m\]#\# !\! \$\[\033[;m\] '`

> `PROMPT_COMMAND='RET=$?; echo; if [ $RET != 0 ] ; then echo "rc: $RET"; fi; if [ "$PWD" != "$HOME" ]; then if [ $( ls -A | wc -l ) -lt 20 ]; then ls -mAF; fi; else ls -mF; fi'`

On my Mac, it looks like this:

![enter image description here][1]

Through color highlighting, the prompt is easily visible between program invocations with lots of output. It shows both the command and history numbers, my user name and full current working directory path, and the number of files in the current directory (both non-hidden and all files).

It prints the previous command's return code unless it's `0`, and lists all files in the current directory if the file count is reasonably low. I prefer this to [functions that combine `cd` and `ls`](http://superuser.com/questions/190554/whats-equivalent-to-alias-cs-cdls-but-with-the-argument-to-cs-going-to-cd), as I can immediately see the changes to the current directory after program execution.

## Persisting changes ##

As I wrote at the beginning, your prompt is not kept across shell sessions when you simply set `PS1` (or `PS2`) in your shell. To keep your changes across sessions and restarts of your machine, add the relevant assignments of `PS1`, `PS2` and `PROMPT_COMMAND` -- one per line -- to your `.bash_profile` or `.bashrc` file in your home directory ([more on these files](http://superuser.com/questions/183870/difference-between-bashrc-and-bash-profile)). Save the file, open a new bash session, and enjoy your custom prompt!

  [1]: https://i.sstatic.net/QaA7m.png