InfinityQuest - Programming Code Tutorials and Examples with Python, C++, Java, PHP, C#, JavaScript, Swift and more

Menu
  • Home
  • Sitemap

Python Programming Language Best Tutorials and Code Examples

Learn Python Right Now!
Home
Bash
Customizing Your Prompt in bash
Bash

Customizing Your Prompt in bash

InfinityCoder April 4, 2017

The default bash prompt is usually something uninformative that ends with $ and doesn’t tell you much, so you would like to customize it to show information you find useful.

Customize the $PS1 and $PS2 variables as you desire.
The default prompt varies depending on your system. bash itself will show its major and minor version (\s-\v\$), for example, bash-3.00$.

However, your operating system may have its own default, such as [user@host ~]$ ([\u@\h \W]\$) for Fedora Core 5.

This solution presents eight basic prompts and three fancier prompts.

Basic prompts Here are eight examples of more useful prompts that will work with bash-1.14.7 or
newer.

The trailing \$ displays # if the effective UID is zero (i.e., you are root) and $ otherwise:

1. Username@hostname, the date and time, and the current working directory:

1
2
3
$ export PS1='[\u@\h \d \A] \w \$ '
[jp@freebsd Wed Dec 28 19:32] ~ $ cd /usr/local/bin/
[jp@freebsd Wed Dec 28 19:32] /usr/local/bin $

2. Username@long-hostname, the date and time in ISO 8601 format, and the basename of the current working directory (\W):

1
2
3
$ export PS1='[\u@\H \D{%Y-%m-%d %H:%M:%S%z}] \W \$ '
[jp@freebsd.jpsdomain.org 2005-12-28 19:33:03-0500] ~ $ cd /usr/local/bin/
[jp@freebsd.jpsdomain.org 2005-12-28 19:33:06-0500] bin $

3. Username@hostname, bash version, and the current working directory (\w):

1
2
3
$ export PS1='[\u@\h \V \w] \$ '
[jp@freebsd 3.00.16] ~ $ cd /usr/local/bin/
[jp@freebsd 3.00.16] /usr/local/bin $

4. New line, username@hostname, base PTY, shell level, history number, newline, and full working directory name ($PWD):

1
2
3
4
5
6
7
$ export PS1='\n[\u@\h \l:$SHLVL:\!]\n$PWD\$ '
 
[jp@freebsd ttyp0:3:21]
/home/jp$ cd /usr/local/bin/
 
[jp@freebsd ttyp0:3:22]
/usr/local/bin$

PTY is the number of the pseudoterminal (in Linux terms) to which you are connected.
This is useful when you have more than one session and are trying to keep track of which is which. Shell level is the depth of subshells you are in.
When you first log in it’s 1, and as you run subprocesses (for example, screen) it increments, so after running screen it would normally be 2.

The history line is the number of the current command in the command history.

5. Username@hostname, the exit status of the last command, and the current working directory.

Note the exit status will be reset (and thus useless) if you execute any commands from within the prompt:

1
2
3
4
5
6
$ export PS1='[\u@\h $? \w \$ '
[jp@freebsd 0 ~ $ cd /usr/local/bin/
[jp@freebsd 0 /usr/local/bin $ true
[jp@freebsd 0 /usr/local/bin $ false
[jp@freebsd 1 /usr/local/bin $ true
[jp@freebsd 0 /usr/local/bin $

6. One other interesting example is showing the number of jobs the shell is currently managing.

This can be useful if you run a lot of background jobs and forget that they are there:

1
2
3
4
5
6
7
8
9
10
11
12
$ export PS1='\n[\u@\h jobs:\j]\n$PWD\$ '
 
[jp@freebsd jobs:0]
/tmp$ ls -lar /etc > /dev/null &
[1] 96461
 
[jp@freebsd jobs:1]
/tmp$
[1]+ Exit 1           ls -lar /etc >/dev/null
 
[jp@freebsd jobs:0]
/tmp$

7. Let’s go really crazy and show everything. Username@hostname, tty, level, history, jobs, version, and full working directory:

1
2
3
4
$ export PS1='\n[\u@\h t:\l l:$SHLVL h:\! j:\j v:\V]\n$PWD\$ '
 
[jp@freebsd t:ttyp1 l:2 h:91 j:0 v:3.00.16]
/home/jp$

8. The next prompt is one you will either love or hate. It shows username@hostname, T for ptty, L for shell level, C for command number, and the date and time in ISO 8601:

1
2
3
4
5
6
7
$ export PS1='\n[\u@\h:T\l:L$SHLVL:C\!:\D{%Y-%m-%d_%H:%M:%S_%Z}]\n$PWD\$ '
 
[jp@freebsd:Tttyp1:L1:C337:2006-08-13_03:47:11_EDT]
/home/jp$ cd /usr/local/bin/
 
[jp@freebsd:Tttyp1:L1:C338:2006-08-13_03:47:16_EDT]
/usr/local/bin$

This prompt shows very clearly who did what, when, and where and is great for documenting steps you took for some task via a simple copy and paste from a scroll-back buffer.

But some people find it much too cluttered and distracting.

Fancy prompts
Here are three fancy prompts that use ANSI escape sequences for colors, or to set the title bar in an xterm.

But be aware that these will not always work. There is a bewildering array of variables in system settings, xterm emulation, and SSH and telnet clients, all of which can affect these prompts.
Also, such escape sequences should be surrounded by \[ and \], which tells bash that the enclosed characters are non-printing.

Otherwise, bash will be confused about line lengths and wrap lines in the wrong place.

1. Username@hostname, and the current working directory in light blue (color not shown in print):

1
2
3
4
$ export PS1='\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '
[jp@freebsd:~]$
[jp@freebsd:~]$ cd /tmp
[jp@freebsd:/tmp]$

2. Username@hostname, and the current working directory in both the xterm title bar and in the prompt itself.

If you are not running in an xterm this may produce garbage in your prompt:

1
2
3
4
$ export PS1='\[\033]0;\u@\h:\w\007\][\u@\h:\w]\$ '
[jp@ubuntu:~]$
[jp@ubuntu:~]$ cd /tmp
[jp@ubuntu:/tmp]$

3. Both color and xterm updates:

1
2
3
4
$ export PS1='\[\033]0;\u@\h:\w\007\]\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '
[jp@ubuntu:~]$
[jp@ubuntu:~]$ cd /tmp
[jp@ubuntu:/tmp]$

To save some tedious typing, the prompts from above are in the bash Cookbook download (http://www.bashcookbook.com), in the file ./ch16/prompts, shown here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# cookbook filename: prompts
 
# User name @ short hostname, the date and time and the current working
# directory (CWD):
export PS1='[\u@\h \d \A] \w \$ '
 
# User name @ long hostname, the date and time in ISO 8601 format and the
# basename of the current working directory (\W):
export PS1='[\u@\H \D{%Y-%m-%d %H:%M:%S%z}] \W \$ '
 
# User name @ short hostname, bash version, and the current working
# directory (\w):
export PS1='[\u@\h \V \w] \$ '
 
# New line, user name @ hostname, base PTY, shell level, history number, new
# line, and full working directory name ($PWD).
export PS1='\n[\u@\h \l:$SHLVL:\!]\n$PWD\$ '
 
# User name @ short hostname, the exit status of the last command and the
# current working directory.
export PS1='[\u@\h $? \w \$ '
 
# Number of jobs in the background
export PS1='\n[\u@\h jobs:\j]\n$PWD\$ '
 
# User, short hostname, tty, level, history, jobs, version and full
# working directory name:
export PS1='\n[\u@\h t:\l l:$SHLVL h:\! j:\j v:\V]\n$PWD\$ '
 
# user@host, T for ptty, L for shell level, C for command number, and the
# date and time in ISO 8601.
export PS1='\n[\u@\h:T\l:L$SHLVL:C\!:\D{%Y-%m-%d_%H:%M:%S_%Z}]\n$PWD\$ '
 
 
# User name @ short hostname, and the current working directory in light
# blue:
export PS1='\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '
 
# User name @ short hostname, and the current working directory in both the
# xterm title bar and in the prompt itself.
export PS1='\[\033]0;\u@\h:\w\007\][\u@\h:\w]\$ '
 
# Both color and xterm updates:
export PS1='\[\033]0;\u@\h:\w\007\]\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\] '

Note that the export command need only be used once to flag a variable to be exported to child processes.
Assuming the promptvars shell option is set, which it is by default, prompt strings are decoded, expanded via parameter expansion, command substitution, and arithmetic expansion, quotes are removed, and they are finally displayed.

Prompt strings are $PS1, $PS2, $PS3, and $PS4. The command prompt is $PS1.

The $PS2 prompt is the secondary prompt displayed when bash needs more information to complete a command.
It defaults to > but you may use anything you like. $PS3 is the select prompt , which defaults to “#?”, and $PS4 is the xtrace (debugging) prompt, with a default of “+”.

Note that the first character of $PS4 is replicated as many times as needed to denote levels of indirection in the currently executing command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ export PS2='Secondary> '
 
$ for i in *
Secondary> do
Secondary> echo $i
Secondary> done
cheesy_app
data_file
hard_to_kill
mcd
mode
 
$ export PS3='Pick me: '
 
$ select item in 'one two three'; do echo $item; done
1) one two three
Pick me: ^C
 
$ export PS4='+ debugging>
 
$ set -x
 
$ echo $( echo $( for i in *; do echo $i; done ) )
+++ debugging> for i in '*'
+++ debugging> echo cheesy_app
+++ debugging> for i in '*'
+++ debugging> echo data_file
+++ debugging> for i in '*'
+++ debugging> echo hard_to_kill
+++ debugging> for i in '*'
+++ debugging> echo mcd
+++ debugging> for i in '*'
+++ debugging> echo mode
++ debugging> echo cheesy_app data_file hard_to_kill mcd mode
+ debugging> echo cheesy_app data_file hard_to_kill mcd mode
cheesy_app data_file hard_to_kill mcd mode

Since the prompt is only useful when you are running bash interactively, the best place to set it is globally in /etc/bashrc or locally in ~/.bashrc.
As a style note, we recommend putting a space character as the last character in the $PS1 string.

It makes it easier to read what is on your screen by separating the prompt string from the commands that you type.

For this, and because your string may contain other spaces or special characters, it is a good idea to use double or even single quotes to quote the string when you assign it to $PS1.
There are at least three easy ways to display your current working directory (CWD) in your prompt: \w, \W, and $PWD. \W will print the basename or last part of the directory, while \w will print the entire path; note that both will print ~ instead of whatever $HOME is set to when you are in your home directory.

That drives some people crazy, so to print the entire CWD, use $PWD. Printing the entire CWD will cause the prompt to change length, and can even wrap in deep directory structures.

That can drive other people crazy. Here is a function to truncate it and a prompt to use the function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# cookbook filename: func_trunc_PWD
 
function trunc_PWD {
  # $PWD truncation code adapted from The Bash Prompt HOWTO:
  # 11.10. Controlling the Size and Appearance of $PWD
  # http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x783.html
 
  # How many characters of the $PWD should be kept
  local pwdmaxlen=30
  # Indicator that there has been directory truncation:
  local trunc_symbol='...'
  # Temp variable for PWD
  local myPWD=$PWD
 
  # Replace any leading part of $PWD that matches $HOME with '~'
  # OPTIONAL, comment out if you want the full path!
  myPWD=${PWD/$HOME/~}
 
  if [ ${#myPWD} -gt $pwdmaxlen ]; then
     local pwdoffset=$(( ${#myPWD} - $pwdmaxlen ))
     echo "${trunc_symbol}${myPWD:$pwdoffset:$pwdmaxlen}"
  else
     echo "$myPWD"
  fi
}

And a demonstration:

1
2
3
4
5
6
7
8
$ source file/containing/trunc_PWD
 
[jp@freebsd ttyp0:3:60]
~/this is a bunch/of really/really/really/long directories/did I mention really/
really/long$ export PS1='\n[\u@\h \l:$SHLVL:\!]\n$(trunc_PWD)\$ '
 
[jp@freebsd ttyp0:3:61]
...d I mention really/really/long$

You will notice that the prompts above are single quoted so that $ and other special characters are taken literally.

The prompt string is evaluated at display time, so the variables are expanded as expected.

Double quotes may also be used, though in that case you must escape shell metacharacters, e.g., by using \$ instead of $.
The command number and the history number are usually different: the history number of a command is its position in the history list, which may include commands restored from the history file, while the command number is the position in the sequence of commands executed during the current shell session.
There is also a special variable called $PROMPT_COMMAND, which if set is interpreted as a command to execute before the evaluation and display of $PS1.

The issue with that, and with using command substitution from within the $PS1 prompt, is that these commands are executed every time the prompt is displayed, which is often.

Fo example, you could embed a command substitution such as $(ls -1 | wc -l) in your prompt to give you a count of files in the current working directory.

But on an old or heavily utilized system in a large directory, that may result in significant delays before the prompt is presented and you can get on with your work.

Prompts are best left short and simple (notwithstanding some of the monsters shown in the Solutions section).
Define functions or aliases to easily run on demand instead of cluttering up and slowing down your prompt.
To work around ANSI or xterm escapes that produce garbage in your prompt if they are not supported, you can use something like this in your rc file:

1
2
3
4
5
case $TERM in
   xterm*) export PS1='\[\033]0;\u@\h:\w\007\]\[\033[1;34m\][\u@\h:\w]\$\[\033[0m\]
' ;;
        *) export PS1='[\u@\h:\w]\$ ' ;;
esac

See the section “Prompt String Customizations” in Appendix A.

Colors
In the ANSI example we just discussed, 1;34m means “set the character attribute to light, and the character color to blue.” 0m means “clear all attributes and set no color.”
See the section “ANSI Color Escape Sequences” in Appendix A for the codes. The trailing m indicates a color escape sequence.
Here is a script that displays all the possible combinations.

If this does not display colors on your terminal, then ANSI color is not enabled or supported.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env bash
# cookbook filename: colors
#
# Daniel Crisman's ANSI color chart script from
# The Bash Prompt HOWTO: 6.1. Colours
# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html.
#
# This file echoes a bunch of color codes to the
# terminal to demonstrate what's available. Each
# line is the color code of one foreground color,
# out of 17 (default + 16 escapes), followed by a
# test use of that color on all nine background
# colors (default + 8 escapes).
#
 
T='gYw' # The test text
 
echo -e "\n           40m    41m     42m     43m\
      44m   45m    46m    47m";
 
for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \
           '1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \
           ' 36m' '1;36m' ' 37m' '1;37m';
   do FG=${FGs// /}
   echo -en " $FGs \033[$FG $T "
   for BG in 40m 41m 42m 43m 44m 45m 46m 47m;
      do echo -en "$EINS \033[$FG\033[$BG $T \033[0m";
   done
   echo;
done
echo

 

Share
Tweet
Email
Prev Article
Next Article

Related Articles

Searching for Text While Ignoring Case in bash
You need to search for a string (e.g., “error”) in …

Searching for Text While Ignoring Case in bash

Selecting from a List of Options in bash
You need to provide the user with a list of …

Selecting from a List of Options in bash

About The Author

InfinityCoder
InfinityCoder

Leave a Reply

Cancel reply

Recent Tutorials InfinityQuest

  • Adding New Features to bash Using Loadable Built-ins in bash
    Adding New Features to bash Using Loadable …
    June 27, 2017 0
  • Getting to the Bottom of Things in bash
    Getting to the Bottom of Things in …
    June 27, 2017 0

Recent Comments

  • fer on Turning a Dictionary into XML in Python
  • mahesh on Turning a Dictionary into XML in Python

Categories

  • Bash
  • PHP
  • Python
  • Uncategorized

InfinityQuest - Programming Code Tutorials and Examples with Python, C++, Java, PHP, C#, JavaScript, Swift and more

About Us

Start learning your desired programming language with InfinityQuest.com.

On our website you can access any tutorial that you want with video and code examples.

We are very happy and honored that InfinityQuest.com has been listed as a recommended learning website for students.

Popular Tags

binary data python CIDR convert string into datetime python create xml from dict python dictionary into xml python how to create xml with dict in Python how to write binary data in Python IP Address read binary data python tutorial string as date object python string to datetime python

Archives

  • June 2017
  • April 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
Copyright © 2021 InfinityQuest - Programming Code Tutorials and Examples with Python, C++, Java, PHP, C#, JavaScript, Swift and more
Programming Tutorials | Sitemap