HOWTO: Change the terminal title when commands are running

In the work I do I often have a lot of terminals open, and some of those terminals have a lot of tabs. Sometimes I start a process that’s going to take a long time and I’d like to quickly see if that process is still running or if it has finished. While this is tricky, it’s possible! This HOWTO is bash-specific and is designed for Ubuntu, but it should work on other distributions with minimal changes. Thanks to this url for getting me started: http://superuser.com/questions/42362/gnome-terminal-process-name-in-tab-title.

Step one is to make sure that your current settings do not change the title of the terminal. On Ubuntu there’s a block of code in the ~/.bashrc file that says “If this is an xterm set the title to user@host:dir“. Just comment out that whole block by putting # characters at the beginning of each line to disable the functionality.

# If this is an xterm set the title to user@host:dir
#case "$TERM" in
#xterm*|rxvt*)
#    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
#    ;;
#*)
#    ;;
#esac

On other systems you will have to look around for where the value of PS1 is set. Look for “\e” — this is the code that tells bash what title you want to use. We want to override this, so delete everything from \e to \a.

Step two is to insert new code into ~/.bashrc (or wherever your system prefers). I put this code right after the existing PS1 code that Ubuntu shipped.

# Custom title-setting code that adds a triangle play-arrow
# if the terminal is not waiting on the prompt
case "$TERM" in
xterm*|rxvt*)
    # This tells bash: before showing the prompt, run this
    PROMPT_COMMAND='echo -ne "\033]0;${THIS_TERMINAL_TITLE}\007"'

    # Edit the title if a command is running:
    # http://www.davidpashley.com/articles/xterm-titles-with-bash.html
    show_command_in_title_bar()
    {
        case "$BASH_COMMAND" in
            *\033]0*)
                # The command is trying to set the title bar as well;
                # this is most likely the execution of $PROMPT_COMMAND.
                # In any case nested escapes confuse the terminal, so don't
                # output them.
                ;;
            *)
                echo -ne "\033]0;▶ ${THIS_TERMINAL_TITLE}\007"
                ;;
        esac
    }
    # The DEBUG signal simply announces the last-run command
    trap show_command_in_title_bar DEBUG
    ;;
*)
    ;;
esac

# Now we can set the title of the terminal with terminal_title my title
function terminal_title ()
{
    export THIS_TERMINAL_TITLE="$@"
}
# Here's a good default
export THIS_TERMINAL_TITLE="$USER@$HOSTNAME"

This code works because of a few obscure features in the bash shell. The first is the existence of $BASH_COMMAND — a variable that holds the value of the currently-running command. Second, the trap command which allows us to take action when commands are executed, and third, the $PROMPT_COMMAND variable which tells bash to execute a command before showing the command prompt. With these features, we can change the title when commands are executed and change the title back when the commands are done executing.

In my case all I do is take the current terminal title and add a play-like triangle character to the beginning while commands are running. When the commands are complete the old title is restored and the triangle disappears. One could extend this feature by taking the value of $BASH_COMMAND and adding it to the title. By default the terminal title is just $USER@$HOSTNAME but I’ve added a function which allows me to change the title to anything I want.

Step three requires you to either log out and log back in for the changes to take effect, or to run source ~/.bashrc in order to execute the commands. Note that some terminals have to be set up properly to allow their titles to be changed. In gnome-terminal, go to Edit / Profile Preferences / Title and Command and make sure “When terminal commands set their own titles” is set to anything except “Keep initial title.” Also, if you have set a custom title in gnome-terminal itself by right clicking a tab and selecting “Set Title…”, you’ll need to erase that custom title by selecting “Set Title…” and erasing the text inside there. This can be a little tricky, and logging out may be the simplest solution. If you’re still not seeing the terminal title change, check echo $PS1 and make sure there is no \e visible.

Now when I run a long compile or test command, I see a ▶ in the titlebar and tab of my terminal. When the triangle disappears I know my command has completed. Please share your favorite extensions to this feature in the comments!