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:
(In our opinion this is just one of many reasons not to use C shells. See Csh Programming Considered Harmful for a useful discussion).
if ($?TERM) then ... endif
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).
zsh
provides some functions and expansions, which we will use:
There are many more expansions available: see the
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 '~'
zshmisc
man page.
Thus, the following will set the xterm title to "username@hostname: directory
":
This could also be achieved by using
case $TERM in xterm*) precmd () {print -Pn "\e]0;%n@%m: %~\a"} ;; esac
chpwd()
instead of precmd()
. The print
builtin works like echo
, but gives us access to the %
prompt escapes.
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
):
However, this gives the directory's full path instead of using
switch ($TERM) case "xterm*": alias precmd 'echo -n "\033]0;${HOST}:$cwd\007"' breaksw endsw
~
. Instead you can insert the string in the prompt:
which sets a prompt of "
switch ($TERM) case "xterm*": set prompt="%{\033]0;%n@%m:%~\007%}tcsh%# " breaksw default: set prompt="tcsh%# " breaksw endsw
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).
bash
supplies a variable $PROMPT_COMMAND
which contains a command to execute before the prompt. This example sets the title to username@hostname: directory
:
where
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
\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
:
Note the use of
case $TERM in xterm*) PS1="\[\033]0;\u@\h: \w\007\]bash\\$ " ;; *) PS1="bash\\$ " ;; esac
\[...\]
, 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.
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$
.
However,
case $TERM in xterm*) HOST=`hostname` PS1='^[]0;${USER}@${HOST}: ${PWD}^Gksh$ ' ;; *) PS1='ksh$ ' ;; esac
$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:
Note that the
HOST=`hostname` HOST=${HOST%%.*} PS1='^[]0;${USER}@${HOST}: ${PWD##${HOME}/}^Gksh$ '
^[
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
).
This is very difficult indeed in csh
, and we end up doing something like the following:
where we have had to alias the
switch ($TERM) case "xterm*": set host=`hostname` alias cd 'cd \!*; echo -n "^[]0;${user}@${host}: ${cwd}^Gcsh% "' breaksw default: set prompt='csh% ' breaksw endsw
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
.