How to: Change / Setup bash custom prompt (PS1)

by Vivek Gite · 34 comments

So how do you setup, change and pimp out Linux / UNIX shell prompt?

Most of us work with a shell prompt. By default most Linux distro displays hostname and current working directory. You can easily customize your prompt to display information important to you. You change look and feel by adding colors. In this small howto I will explain howto setup:
a] Howto customizing a bash shell to get a good looking prompt
b] Configure the appearance of the terminal.
c] Apply themes using bashish
d] Howto pimp out your shell prompt

Prompt is control via a special shell variable. You need to set PS1, PS2, PS3 and PS4 variable. If set, the value is executed as a command prior to issuing each primary prompt.

  • PS1 - The value of this parameter is expanded (see PROMPTING below) and used as the primary prompt string. The default value is \s-\v\$ .
  • PS2 - The value of this parameter is expanded as with PS1 and used as the secondary prompt string. The default is >
  • PS3 - The value of this parameter is used as the prompt for the select command
  • PS4 - The value of this parameter is expanded as with PS1 and the value is printed before each command bash displays during an execution trace. The first character of PS4 is replicated multiple times, as necessary, to indicate multiple levels of indirection. The default is +

How do I display current prompt setting?

Simply use echo command, enter:
$ echo $PS1
Output:

\\u@\h \\W]\\$

How do I modify or change the prompt?

Modifying the prompt is easy task. Just assign a new value to PS1 and hit enter key:
My old prompt --> [vivek@105r2 ~]$
PS1="touch me : "
Output: My new prompt

touch me : 

So when executing interactively, bash displays the primary prompt PS1 when it is ready to read a command, and the secondary prompt PS2 when it needs more input to complete a command. Bash allows these prompt strings to be customized by inserting a number of backslash-escaped special characters that are decoded as follows:

  • \a : an ASCII bell character (07)
  • \d : the date in "Weekday Month Date" format (e.g., "Tue May 26")
  • \D{format} : the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a locale-specific time representation. The braces are required
  • \e : an ASCII escape character (033)
  • \h : the hostname up to the first '.'
  • \H : the hostname
  • \j : the number of jobs currently managed by the shell
  • \l : the basename of the shell’s terminal device name
  • \n : newline
  • \r : carriage return
  • \s : the name of the shell, the basename of $0 (the portion following the final slash)
  • \t : the current time in 24-hour HH:MM:SS format
  • \T : the current time in 12-hour HH:MM:SS format
  • \@ : the current time in 12-hour am/pm format
  • \A : the current time in 24-hour HH:MM format
  • \u : the username of the current user
  • \v : the version of bash (e.g., 2.00)
  • \V : the release of bash, version + patch level (e.g., 2.00.0)
  • \w : the current working directory, with $HOME abbreviated with a tilde
  • \W : the basename of the current working directory, with $HOME abbreviated with a tilde
  • \! : the history number of this command
  • \# : the command number of this command
  • \$ : if the effective UID is 0, a #, otherwise a $
  • \nnn : the character corresponding to the octal number nnn
  • \\ : a backslash
  • \[ : begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
  • \] : end a sequence of non-printing characters

Let us try to set the prompt so that it can display today’d date and hostname:
PS1="\d \h $ "
Output:

Sat Jun 02 server $ 

Now setup prompt to display date/time, hostname and current directory:
$ PS1="[\d \t \u@\h:\w ] $ "
Output:

[Sat Jun 02 14:24:12 vivek@server:~ ] $

How do I add colors to my prompt?

You can change the color of your shell prompt to impress your friend or to make your own life quite easy while working at command prompt.

Putting it all together

Let us say when you login as root/superuser, you want to get visual confirmation using red color prompt. To distinguish between superuser and normal user you use last character in the prompt, if it changes from $ to #, you have superuser privileges. So let us set your prompt color to RED when you login as root, otherwise display normal prompt.

Open /etc/bashrc (Redhat and friends) / or /etc/bash.bashrc (Debian/Ubuntu) or /etc/bash.bashrc.local (Suse and others) file and append following code:
# vi /etc/bashrc
or
$ sudo gedit /etc/bashrc
Append the code as follows

# If id command returns zero, you’ve root access.
if [ $(id -u) -eq 0 ];
then # you are root, set red colour prompt
  PS1="\\[$(tput setaf 1)\\]\\u@\\h:\\w #\\[$(tput sgr0)\\]"
else # normal
  PS1="[\\u@\\h:\\w] $"
fi

Close and save the file.

My firepower prompt

Check this out:
Firepower shell prompt using bashish
(click to enlarge)

You can also create complex themes for your bash shell using bashish. Bashish is a theme enviroment for text terminals. It can change colors, font, transparency and background image on a per-application basis. Additionally Bashish supports prompt changing on common shells such as bash, zsh and tcsh. Install bashish using rpm or apt-get command:
# rpm -ivh bashish*
OR
# dpkg -i bashish*
Now start bashish for installing user configuration files:
$ bashish
Next you must restart your shell by typing the following command:
$ exec bash
To configure the Bashish theme engine, run
$ bashishtheme

basish in action (screenshots from official site):
flower.png

urbandawn - based on an artwork by grevenlx
Finally, you can always use aterm or other terminal program such as rxvt. It supports nice visual effect , like transparency, tinting and much more by visiting profile menu. Select your terminal > click on Edit menu bar > Profiles > Select Profile > Click on Edit button > Select Effects tab > Select transparent background > Close

Linux desktop nice visual effect , like transparency, tinting etc
(click to enlarge)

Further readings:

Featured Articles:

Want to read Linux tips and tricks, but don't have time to check our blog everyday? Subscribe to our daily email newsletter to make sure you don't miss a single tip/tricks. Subscribe to our weekly newsletter here!

{ 34 comments… read them below or add one }

1 akashdeep 06.03.07 at 9:12 am

LOL .. nice your command is my wish

2 Kirk Strauser 06.13.07 at 1:01 pm

Here’s my ZSH prompt. I start by defining a bunch of complicated variables, then actually build the prompt with a much more legible set of instructions.


# Define common and useful things to put in a prompt
typeset -A prc
prc[abbrevpath]='%{${fg[red]}%}%B%45

The result is like:


kirk@mysystem [7:54} ~
:) $

where "kirk@mysystem" is green for normal users and red for root. The time is blue. The current directory is in red, and if it's longer that a set amount, the beginning is replaced with " ... " (so that you always see bottommost directory you're in). The smiley face is ":)" in green if the last command you typed executed correctly, or ":(" in red if it didn't. "$" is black, and if you're root, it's "#" instead.

It packs a lot of useful information into a small area, like who you are, where you are, whether you're root, and whether you can make commands that succeed. If I see too many red frowns, I call it quits for the day.

I think you can do most of this in Bash, too, but I never got that creative.

3 SimpleSimon 11.27.07 at 2:47 am

Two things that I’d like to know how to do (if possible) with my bash prompt…

1) Include the full path of the current directory, but only the last 25 characters if the path is longer than that. I’d also prefer a shortened path to be preceeded by “…”.

2) Memorize the current cursor position, drop to the bottom line of the screen, output my prompt info, jump back to the previous cursor position.

Either of these possible?

4 chika 01.24.08 at 3:51 pm

how to eliminate the hostname on the konsole?
what should i add?

5 chika 01.26.08 at 5:42 pm

hey chika do this on your console

PS1=”\d $”

6 oscar 04.17.08 at 8:51 pm

How to change the prompt when access is via ssh, I have tried and don’t find that setting.
Debian

7 Jamie 04.23.08 at 12:24 am

@ SimpleSimon

For your first question, you want to look at the PROMPT_COMMAND variable. I don’t have an answer for your second question.

Example:
# This will limit the path to 30 characters.
PROMPT_COMMAND=’if [ ${#PWD} -gt 30 ]; then myPWD=${PWD:0:12}…${PWD:${#PWD}-15}; else myPWD=$PWD; fi’
PS1=”\u@\h \$myPWD\$ ”

HTH,
Jamie

8 Reddy 09.02.08 at 10:12 am

Thank you very much

9 Steve 11.06.08 at 4:20 pm

On slackware, I simply want:

/home/steve $

unless I su to root, then I want

/home/steve #

It would seem that this should do it:

if [ $(id -u) -eq 0 ];
then # you are root
PS1=”$PWD #”
else # normal
PS1=”$PWD $”
fi

but after suing to root I still get

/home/steve $

How would I fix this?

10 Dan 11.25.08 at 10:07 pm

Steve, you may need to create .shrc file or whichever you’re using under root’s home directory so it gets sourced when you log in or sudo as root.

11 Balaji 11.27.08 at 8:15 pm

hi,

how to accept the prompt value into a variable.

x=echo $PS1 : this is not working

thanks,
Balaji

12 vivek 11.27.08 at 8:20 pm

Balaji,

Use following code

x=$(echo $PS1)
echo $x
13 Balaji 11.27.08 at 8:31 pm

Hi Vivek,

i still get an error.

bash-2.05b$ promt.ksh
$
./promt.ksh[7]: syntax error: `1′ unexpected

bash-2.05b$ cat promt.ksh
#!/bin/ksh

x=$(echo $PS1)

echo $x

exit (1)

14 Bret Sutton 11.30.08 at 9:46 am

As the error message says, the error is on line 7, which appears to be your exit command. If you want to exit with a non-zero return code, use a number without parentheses.

15 Steve 12.14.08 at 1:27 pm

Dan, you were exactly right, almost. Slackware used bash for both user and root. I ended up with

export PS1=’\e[0;32m$PWD $\e[m ‘

in ~/.bashrc

and

export PS1=’\e[0;31m$PWD #\e[m ‘

in /root/.bashrc

and I not only get what I want, but I get Christmas colors, too. Thanks for the tip and this article.

16 Reg Whitton 01.06.09 at 12:07 pm

@ SimpleSimon

My answer for question 1:

PS1='${PWD/????????????????????????????*/...${PWD:${#PWD}-25}} '

Note: I used 28 question marks otherwise the … could make the string longer. If you reduce it to 25 then use ${#PWD}-22 in the substring length.

Question 2, answer 1:

I have tried this out but I can’t recommend it. I would recommend anser 2 below. However it is interesting to show what can be done.

You need to look at /etc/termcap for your terminal (xterm) in my case, and at the meaning of the tcap codes in terminfo.

In particular:
sc – save cursor
rc – restore cursor
cm – cursor move
ce – clear to end of line

These can take quite a bit of understanding, but my “cm” is \E[%i%d;%dH which means that in my PS1 that \e[1;1H would move the cursor to the top of the screen (the first number is the row). If there is no %i in the "cm" then numbers start from zero.

My "sc" is \E7
My "rc" is \E8
My "ce" is \E[K

So setting PS1 thus:

PS1='${PWD/????????????????????????????*/...${PWD:${#PWD}-25}} \e7\e[1;1H\w\e[K\e8'

Will write the current directory on the top line of the screen.

Next you need to ensure that the checkwinsize is set.

shopt -s checkwinsize

You might put it in your ".bashrc" . This sets the LINES and COLUMNS variables after every external command.

Now try setting PS1 thus:

PS1='${PWD/????????????????????????????*/...${PWD:${#PWD}-25}} \e7\e[$LINES;1H\w\e[K\e8'

This will write the directory at the bottom left. However, this is not good as using the top line. Once the screen is full, bash and program output will mangle the directory line.

Hence I recommend answer 2.

Question 2, answer 2:

Assuming that you are using a virtual terminal - you can often put the current directory (or other info) into title of the window.

I use bash on Windows/Cygwin and by default PS1 set thus:

PS1='\[\e]0;\w\a\]\n\[\e[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\n\$ '

This makes the prompt:

user@host directory
$

in pretty colours and puts the current directory in the title for the xterm or ansi console (rxvt or Windows command window). If you use another terminal emulator you may need to find other command codes that do this.

This works well except the newline in the prompt can muck up the editing of very long previous commands. However, if you use the answer to question 1 you could remove it.


PS1='\[\e]0;\w\a\]\n\[\e[32m\]\u@\h \[\e[33m\]'${PWD/????????????????????????????*/...${PWD:${#PWD}-25}}\[\e[0m\]\n\$ '

17 milo 02.12.09 at 5:48 am

Use the csh shell … if by mistake u have moved to another shell like bash

18 irvy 04.15.09 at 1:01 am

How can I get the /home rather than ~ ?

19 Vivek Gite 04.15.09 at 7:50 am

cd /home

20 Kia 05.01.09 at 8:06 pm

irvy — I think Vivek may have misunderstood you. You get the /home rather than the abbreviated ~ path by using $PWD (instead of \w or \W for instance). You shouldn’t have to precede it by \, either. There are examples above. Good luck.

21 QZ 05.27.09 at 7:42 am

Hey, I absolutely *love* the desktop background in that example. Waterfall and desert and crazy sky; pure adventure. Can you tell me where to find it or even email me a copy? Thanx!

22 Dominique Michel 06.08.09 at 6:39 pm

My fully localised prompt:

export PS1="\e[01;33m# \e[01;35m\D{%A %e %B %G %R %Z} \e[00;31m\u\e[01;32m@\e[00;31m\h \e[01;33m\w :\e[00m\n"

It give something like:
# lundi 8 juin 2009 20:15 CEST dom@tuxstudio ~ :


The # at the beginning associated with the final newline make this prompt absolutely perfect to copy and paste stuffs.

23 salil jain 06.18.09 at 9:20 pm

Hey, I just customised a ubuntu liveCD without the XWindows system installed, but the bash that i’m getting has very odd looking fonts , how can i change those? please advise.
Thanks
~Salil

24 sharmila 10.05.09 at 11:18 am

how to change the diectory using go function

25 CT 10.15.09 at 4:18 am

@ QZ did you ever get a response back regarding that wonderful wallpaper image?
I’m interested in it as well! It looks great!

26 Paramjeet singh 10.20.09 at 7:00 am

hii
Thank U for help

27 ahmed 11.13.09 at 7:49 pm

I am not getting the desired prompt. this is my .profile
PS1=”[\d \t \u@\h:\w ] $ ”
export PS1

prompt is the below one:
[d t u@h:w ] $

what is wrong I am doing here? any help appreciated.

Thanks

28 Kunchok 11.14.09 at 9:23 pm

@ahmed
Bash treats backslash characters specially in double quoted strings. Try single quotes around the prompt specification
PS1=’[\d \t \u@\h:\w]$ ‘

29 Ahmed 11.16.09 at 7:01 pm

I tried single quotes as below:
PS1=’[\d \t \u@\h:\w ] $ ‘

it still gives the same output:
[d t u@h:w ] $

30 bob 11.27.09 at 5:40 pm

@Ahmed:
” and ” are different characters, try replacing them using copy/paste.

My PS1 var is:
export PS1=”\u [\W] \$ “

31 Ahmed 11.28.09 at 2:11 pm

Thanks Bob,

I tried copy pasting in my .profile, but it is getting copied as export PS1=.\u [\W] \$ .
“ is replaced by .(dot). which keystroke will type this “?

32 bob 12.02.09 at 3:10 pm

@Ahmed:
You could try copying the character from the ~/.bashrc file itself, for example at lines 5-6:
# If not running interactively, don’t do anything
[ -z "$PS1" ] && return

The double quotes look different on my side and on the site. There are “strait” quotation marks (unicode 0022) and English quotation marks (unicode 201C / 201D). The site converts the first one into the second one.
Maybe try editing the line with another text editor (nano, vi…) and/or copy the quotation marks from the same file, not from the web site.

For unicode characters, check:
http://triggertek.com/r/unicode/0020-007F
http://triggertek.com/r/unicode/2000-206F

33 david 01.19.10 at 12:50 am

I set PS1=”[\u@\h:\w]\$ ” in my .bashrc file, however, when I type bash at a cmd.exe window the I get

C:\utils>bash
bash: $’\r’: command not found
[david@DESKTOP:/cygdrive/c/utils]$

- the cursor is located on the [ at the start of the line rather than after the $?
- why does the $\r mean?

Any help welcomed.
Thanks.
david

34 John Cochran 02.08.10 at 2:29 pm

my issue is that my screen size is 140 characters. Due to my PS1 config, my command line actually starts in column 23, that leaves 117 characters possible. Whenever I use AIX or Solaris, I can fill the entire line, and then go to the next line and keep going until I hit enter or some limit like 512 or something. What drives me up a wall with linux is that it can only show 25 characters, then shifts left or right. How can I get linux to display the entire command line and quit that 25 character shuffle crap.

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Previous post:

Next post: