Setting a Bash Prompt in OS X


Bash is the default command line shell on OS X and most Linux distributions. The prompt that appears before a command can be easily changed - here’s what I changed mine to, and how.

My bash prompt

Here’s the prompt I use

Writing the prompt in the .bash_profile file

Normally you change the prompt shell by editing the file .bash_profile in your home directory. I do that using nano, a text editor that works inside the shell. If .bash_profile doesn’t exist, it will be created.

nano ~/.bash_profile

I like nano because it shows you the commands you can run at the bottom - All you need to know to use them is that the symbol ^ stands for the [CTRL] key.

A simple example - the default OS X shell prompt

The prompt itself is just an environmental variable like any other, loaded by the shell application as it starts up. It is called PS1 on bash (short for Prompt Shell, I suppose). There is also a PS2, which bash displays when more input is required; most people leave that as it comes by default, with a simple >. And there is also a SUDO_PS1, which is used when you switch to superuser using sudo.

You can put anything you want in your shell prompt(s), normal text or special characters that means something to bash, like “show the date” or “make a beep sound”. You can also have colors, or a script that generates something for you before each command. Some people have scripts that fetch ‘quote of the day’ or suchlike, or, more usefully, the git branch they are working on.

You can see what you got there by simply echoing it. For example, here it is showing is the default OS X prompt:

your-machine:~ you# echo $PS1
\h:\W \u\$

your-machine:~ you is the default bash prompt in OS X as it appears to you. \h:\W \u\$ is how you tell bash to display that prompt. It looks scary, but it’s just a list of special characters - each starting with a slash.

the hostname up to the first ‘.’ - that would be the “your-machine” bit
the current directory - that’s the “~” when you first start Terminal, i.e. your home directory
the current user - i.e. “you”
either # or $ depending on whether you are root or not

You can scroll to the bottom of this page afor a complete list of these special characters.

Breaking down my shell prompt

Refer back to the gist above. The bit of code that goes if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then tries to work out whether the shell supports colours or not (most do). Then comes the prompt \n[\t] \[\e[01;33m\]\u@\H\[\e[0m\]:\$PWD\n

A new line - I like space between commands
the time, surrounded by [ and ] - useful when logging into remote servers, so you can tell what the local time is
this tells bash that what follows are formatting instructions, not something that should be printed
“here comes a color sequence”
this is yellow, bold
this tells bash that formatting instructions are over, and it should start printing again
username - helpful when doing admin on remote servers
just the @, no special meaning
the hostname, i.e. the name of the machine
this is another sequence of formatting instruction - it switches off the bold yellow, and goes back to white
just a colon
the environmental variable $PWD, i.e. the current path but starting from the root. You need to escape the $ as \$ because bash needs to know it is dealing with a non-PS1 special variable, $PWD, and not the string “$PWD”
A new line - because the prompt is quite long, the command itself starts on its own line.

A special shell prompt for sudo

Inspired by this macworld article, I created a slightly different variant for sudo. SUDO_PS1="\n[\t] \[\e[33;01;41m\]\u@\H\[\e[0m\]:\$PWD\n The only difference is the color around the username - 33;01;41m instead of 01;33m. That adds a red background to the prompt, which reminds me I am currently in sudo.

What it looks like

So here’s the prompt, in normal and sudo versions

[12:32:28] ME@my-latptop.lan:/Users/ME/work/blog
sudo -s
[12:35:31] root@my-latptop.lan:/Users/ME/work/blog

More info

A couple of links I found useful.

Bash special characters (OS X version)

\a an ASCII bell character (07) \d the date in "Weekday Month Date" format (e.g., "Tue May 26") \D{format} a date formatted as per the strftime(3) function. 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 \] end a sequence of non-printing characters