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 theprecmd () 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 usingcase $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 usingswitch ($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:
wherePROMPT_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 ofcase $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 theHOST=`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 theswitch ($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.