How to change the title of an xterm: Examples for different shells

Next Previous Contents

## 4. Examples for different shells

Below we provide an set of examples for some of the more common shells. We start with `zsh` as it provides several facilities that make our job much easier. We will then progress through increasingly difficult examples.

In all the examples we test the environment variable `$TERM` to make sure we only apply the escapes to xterms. We test for `$TERM=xterm*`; the wildcard is because some variants (such as rxvt) can set `$TERM=xterm-color`.

We should make an extra comment about C shell derivatives, such as `tcsh` and `csh`. In C shells, undefined variables are fatal errors. Therefore, before testing the variable `$TERM`, it is necessary to test for its existence so as not to break non-interactive shells. To achieve this you must wrap the examples below in something like:

> `

>       if ($?TERM) then
>           ...
>       endif

> `

(In our opinion this is just one of many reasons not to use C shells. See Csh Programming Considered Harmful for a useful discussion).

The examples below should be used by inserting them into the appropriate shell initialisation file; i.e. one that is sourced by interactive shells on startup. In most cases this is called something like `.shellrc` (e.g. `.zshrc`, `.tcshrc`, etc).

## 4.1 zsh

`zsh` provides some functions and expansions, which we will use:

> `

>     precmd ()   a function which is executed just before each prompt
>     chpwd ()    a function which is executed whenever the directory is changed
>     \e          escape sequence for escape (ESC)
>     \a          escape sequence for bell (BEL)
>     %n          expands to $USERNAME
>     %m          expands to hostname up to first '.'
>     %~          expands to directory, replacing $HOME with '~'

> `

There are many more expansions available: see the `zshmisc` man page.

Thus, the following will set the xterm title to "`username@hostname: directory`":

> `

>     case $TERM in
>         xterm*)
>             precmd () {print -Pn "\e]0;%n@%m: %~\a"}
>             ;;
>     esac

> `

This could also be achieved by using `chpwd()` instead of `precmd()`. The `print` builtin works like `echo`, but gives us access to the `%` prompt escapes.

## 4.2 tcsh

`tcsh` has some functions and expansions similar to those of `zsh`:

> `

>     precmd ()   a function which is executed just before each prompt
>     cwdcmd ()   a function which is executed whenever the directory is changed
>     %n          expands to username
>     %m          expands to hostname
>     %~          expands to directory, replacing $HOME with '~'
>     %#          expands to '>' for normal users, '#' for root users
>     %{...%}     includes a string as a literal escape sequence

> `

Unfortunately, there is no equivalent to `zsh`'s `print` command allowing us to use prompt escapes in the title string, so the best we can do is to use shell variables (in `~/.tcshrc`):

> `

>     switch ($TERM)
>         case "xterm*":
>             alias precmd 'echo -n "\033]0;${HOST}:$cwd\007"'
>             breaksw
>     endsw

> `

However, this gives the directory's full path instead of using `~`. Instead you can insert the string in the prompt:

> `

>     switch ($TERM)
>         case "xterm*":
>             set prompt="%{\033]0;%n@%m:%~\007%}tcsh%# "
>             breaksw
>         default:
>             set prompt="tcsh%# "
>             breaksw
>     endsw

> `

which sets a prompt of "`tcsh%` ", and an xterm title and icon of "`username@hostname: directory`". Note that the "`%{...%}`" must be placed around escape sequences (and cannot be the last item in the prompt: see the `tcsh` man page for details).

## 4.3 bash

`bash` supplies a variable `$PROMPT_COMMAND` which contains a command to execute before the prompt. This example sets the title to `username@hostname: directory`:

> `

>     PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'

> `

where `\033` is the character code for `ESC`, and `\007` for `BEL`.

Note that the quoting is important here: variables are expanded in `"..."`, and not expanded in `'...'`. So `$PROMPT_COMMAND` is set to an unexpanded value, but the variables inside `"..."` are expanded when `$PROMPT_COMMAND` is used.

However, `$PWD` produces the full directory path. If we want to use the `~` shorthand we need to embed the escape string in the prompt, which allows us to take advantage of the following prompt expansions provided by the shell:

> `

>     \u          expands to $USERNAME
>     \h          expands to hostname up to first '.'
>     \w          expands to directory, replacing $HOME with '~'
>     \$          expands to '$' for normal users, '#' for root
>     \[...\]     embeds a sequence of non-printing characters

> `

Thus, the following produces a prompt of `bash$` , and an xterm title of `username@hostname: directory`:

> `

>     case $TERM in
>         xterm*)
>             PS1="\[\033]0;\u@\h: \w\007\]bash\\$ "
>             ;;
>         *)
>             PS1="bash\\$ "
>             ;;
>     esac

> `

Note the use of `\[...\]`, which tells `bash` to ignore the non-printing control characters when calculating the width of the prompt. Otherwise line editing commands get confused while placing the cursor.

## 4.4 ksh

`ksh` provides little in the way of functions and expansions, so we have to insert the escape string in the prompt to have it updated dynamically. This example produces a title of `username@hostname: directory` and a prompt of `ksh$` .

> `

>     case $TERM in
>         xterm*)
>             HOST=`hostname`
>             PS1='^[]0;${USER}@${HOST}: ${PWD}^Gksh$ '
>             ;;
>         *)
>             PS1='ksh$ '
>             ;;
>     esac

> `

However, `$PWD` produces the full directory path. We can remove the prefix of `$HOME/` from the directory using the `${...##...}` construct. We can also use `${...%%...}` to truncate the hostname:

> `

>     HOST=`hostname`
>     HOST=${HOST%%.*}
>     PS1='^[]0;${USER}@${HOST}: ${PWD##${HOME}/}^Gksh$ '

> `

Note that the `^[` and `^G` in the prompt string are single characters for `ESC` and `BEL` (can be entered in emacs using `C-q ESC` and `C-q C-g`).

## 4.5 csh

This is very difficult indeed in `csh`, and we end up doing something like the following:

> `

>     switch ($TERM)
>         case "xterm*":
>             set host=`hostname`
>             alias cd 'cd \!*; echo -n "^[]0;${user}@${host}: ${cwd}^Gcsh% "'
>             breaksw
>         default:
>             set prompt='csh% '
>             breaksw
>     endsw

> `

where we have had to alias the `cd` command to do the work of sending the escape sequence. Note that the `^[` and `^G` in the string are single characters for `ESC` and `BEL` (can be entered in emacs using `C-q ESC` and `C-q C-g`).

Notes: on some systems `hostname -s` may be used to get a short, rather than fully-qualified, hostname. Some users with symlinked directories may find ``pwd`` (backquotes to run the `pwd` command) gives a more accurate path than `$cwd`.

Next Previous Contents