Jun 15, 2012

Manage your bash prompt

In this post I want to show a simple yet clever trick to manage the prompt for your interactive shell sessions. For obvious (and unfortunate) popularity reasons, the code example I give is in bash; however it should not be very difficult to translate them to other shells. My goal is more to open your eyes to this helpful trick, rather than give you some guru incantation that will make your life (well your computing) better. This post is targeted at people who spend the better half of their day working on a Unix command line interpreter and want to improve their overall experience.

Bi-modal shells

The Unix shell operates in two modes: "script" (sometimes called "batch", by really old people over 30) and "interactive". In the former, input is read from a file on disk, or for the more modern shells, from the command line arguments. In the latter mode, the commands are input manually by the user and evaluated one at a time. This is a concept familiar to dynamic languages programmers out there, referred to as the REPL, read-eval-print loop.

To make things simple: The interactive mode is what you get when you launch your (x)terminal and script mode is what you get when you execute code written in your favorite text editor.

The shell behaves more or less the same way regardless of what mode it is in. Newcomers are often surprised to see seasoned shell gurus write for and while loops from their interactive sessions, but if you think about it, there's nothing really shocking about that.

The main difference between the two modes happens at initialization. Scripts do not need to load as much info in their environments, and for performance reasons, they don't do. One example of information used exclusively in interactive sessions is aliasing. Aliases exist to make your interactive sessions easier, but shouldn't be used in your scripts, and accordingly aren't loaded unless needed.

The prompt is another example of features that are only present in interactive shells.

The prompt

In its simplest form, the prompt is a string displayed by the shell on the screen before asking for user input. The truth is a bit more complex than that, and different shells operate their prompts differently. I suggest you look at the man page of your shell to understand how it behaves.

In all the shells I have come across, the prompt is simply a string held in the variable PS1. Script shells will simply leave this variable empty, dispensing themselves from prompting. Special characters have special meanings in this variable. As mentioned, they may vary according to the shell you're using. Here're some examples taken from the bash(1) man page:

\dthe date in "Weekday Month Date" format (e.g., "Tue May26")
\hthe hostname up to the first `.'
\Hthe hostname
\jthe number of jobs currently managed by the shell
\rcarriage return
\sthe name of the shell, the basename of $0 (the portion following the final slash)
\tthe current time in 24-hour HH:MM:SS format
\Tthe current time in 12-hour HH:MM:SS format
\@the current time in 12-hour am/pm format
\Athe current time in 24-hour HH:MM format
\uthe username of the current user
\vthe version of bash (e.g., 2.00)
\wthe current working directory, with $HOME abbreviated with a tilde (uses the value of the PROMPT_DIRTRIM variable)
\$if the effective UID is 0, a #, otherwise a $

What good is the prompt? As you can see from the above, prompts are usually used to indicate some information about your current session:
  • What is the current user? (useful for multi-user environments, or if you log in as root often)
  • What is the current working directory?
  • Display the current time next to a command?
  • What's the name of the machine I'm currently logged in?
  • What is the value of $VARIABLE at this particular moment?

These are simply examples of what a prompt can display. The more you get versed in shell-fu, you will be tempted to push the limits of how to take advantage of the prompt. Some people use it to monitor load, cpu/memory consumption, temperature, network traffic, new emails in their inbox ... For those familiar with it, the prompt is the command line equivalent of Conky. Using it right is not just pretty, it's ... better.

Modify the prompt

I've mentioned it before, modifying the prompt consists of modifying the PS1 variable. This can be done completely dynamically. Open an instance of your shell and type:

PS1="hello \u $"

You'll see the prompt change and understand what I mean. Of course to make this change permanent you want to append this line to your init files (~/.bashrc or else, depending on your environment).

The trick: modify dynamically

Now this is the small trick that prompted (no pun intended) me to write this article. It is often useful to modify the prompt dynamically during your work sessions. For instance, if you are displaying the current working directory and the path becomes too long. Or if you want to turn on/off a temporary setting, like displaying the date in your prompt. I have something similar in my own bashrc:

Interactively, I can call the prompt() function at any moment to modify dynamically the value of the prompt. Before this function, I would lose a few minutes each time I wanted to modify the prompt. These minutes definitely had an impact on my productivity and concentration. Take this simple function, play with it and adapt it to your needs. I can attest it is a very good habit to think of the prompt as a powerful tool, instead of annoying text taking up space in the screen.