Making your command line prompt cool – exploring PS1, PROMPT_COMMAND and other environment variables

Let’s start with an extremely basic prompt so we can see how subtle changes affect it. If you export PS1=’a string of text’, your prompt will be exactly ‘a string of text’, unless you use one of the special PS1 codes ‘\u, \h, \w’:

Other PS1 codes include:

u - the current user's username
h - the current machine's hostname
j - the number of jobs managed by this shell
@ - the current time (12 hour format)
d - the current date
w - path of the current working directory
W - just the current working directory
e - an ASCII escape character (033)
n - adds a newline character

Adding colors is the next step. Bash reads a color code and colorizes everything after that, until it reads a new one. And I mean everything. You need to end your PS1 with the color code you want to type in.

In pseudocode,
export PS1='code1 item code2 item2 coode3 item3'

This results in item having color for “colorcode”, item2 having colorcode2, item3 having colorcode3, and we exit with colorcode4 which will be the color of your commands you type.

We can combine several codes together if they are compatible. For example, 0 is default, 1 is bold. So 1;32 means bold and yellow. \033[1;36m means, to bash “beginning a color code, make it bold, and make it cyan.” You can keep adding color codes, and if they don’t override the last one, they will just add:

echo -e '\033[1m make it bold, and \033[36m make it \033[31m red \033[31;103m with a yellow background'

My usual PS1 is: export PS1='\[\033[1;33m\]\u\[\033[0;36m\]@\[\033[1;32m\]\h\[\033[1;37m\]:\[\033[1;31m\]\w \[\033[1;96m\]\$ \[\033[0m\]', or something like this. Let’s break it down by bolding the color codes

export PS1='\[\033[1;33m\]\u\[\033[0;36m\]@\[\033[1;32m\]\h\[\033[1;37m\]:\[\033[1;31m\]\w \[\033[1;36m\]\$ \[\033[0m\]'

export PS1='\[\033[1;33m\]\u\[\033[0;36m\]@\[\033[1;32m\]\h\[\033[1;37m\]:\[\033[1;31m\]\w \[\033[1;96m\]\$ \[\033[0m\]'

The PROMPT_COMMAND environment variable executes a command each time your prompt returns to you. It can be used to give your PS1 some dynamic ability – the ability to update depending on the current state of the system, outside of the limited PS1 codes. The only way I’ve been able to use it meaningfully is to print the system memory available.

export PROMPT_COMMAND='echo -en "\033[m\033[38;5;2m"$(( `sed -n "s/MemFree:[\t ]\+\([0-9]\+\) kB/\1/p" /proc/meminfo`/1024))"\033[1;38;5;22m/"$((`sed -n "s/MemTotal:[\t ]\+\([0-9]\+\) kB/\1/Ip" /proc/meminfo`/1024 ))MB ""'

Messing with LS_COLORS

I’ll first set LS_COLOR='' Below, you’ll see that nothing is colored, except for the directories which are blue, because of another environment variable called DIR_COLORS. We are going to learn how to tell LS_COLORS to colorize files by name.

I usually had colored by files by whether or not they were executable, a symbolic link, etc, which something like LS_COLORS='di=96:fi=0:ln=33:ex=1;92' which sets

  • directories to 96 (cyan)
  • files to 0 (default)
  • links to 33 (yellow)
  • executables to 92 (green)

and so on.

I realized recently you can set LS_COLORS to colorize files by name. This is useful in times where you know many types of files will be present in a directory and you want to see what they are right away. Or even if its not that useful, it’s still pretty cool.

Here I know I have .tex, .aux, .log, .bib, .png, .zip, and .pdf all in this directory. I do LS_COLORS='*.png=96:*.aux=90:*.bib=94:*.log=1;90:*.pdf=1;93:*.tex=93:*.zip=91:di=1;94'

Notice how you can set bold and a color with 1;COLOR.


Since you can take this to extremes, I did.  I quite like it – I use colored pens in real life, so when I discovered this, I just had to …


🙂 Enjoy the pretty prompts!

Leave a Reply

Your email address will not be published. Required fields are marked *