Jun 2007
In a recent text configuring
colors for the Bash
prompt was discussed. In this text a method of messing with the
prompt is expanded upon by actually inserting a shell
code function inline with the bash
prompt.
The bash prompt has built in commands that use escape character
syntax. By default a lot of packages ship bash with a default that
shows the hostname and relative path. The escape sequences for all
users is usually kept in /etc/bashrc or a similar
system location. The sequences themselves might look something like
this:
PS1="[\u@\h:\w]\$
The above settings would look like:
[username@hostname:current_working_directory]$
Or a real example:
[jrf@vela:~/www/systhread.net/texts]$
The Bash Prompt HOWTO is a great resource for looking at different things that can be done with a prompt. Here are the escape sequences per the Bash man page that can be used:
When executing interactively, bash displays the primary
prompt PS1 when it is ready to read a command, and the
secondary prompt PS2 when it needs more input to complete
a command. Bash allows these prompt strings to be cus
tomized by inserting a number of backslash-escaped special
characters that are decoded as follows:
\a an ASCII bell character (07)
\d the date in "Weekday Month Date" format
(e.g., "Tue May 26")
\e an ASCII escape character (033)
\h the hostname up to the first `.'
\H the hostname
\j the number of jobs currently managed by the
shell
\l the basename of the shell's terminal device
name
\n newline
\r carriage return
\s the name of the shell, the basename of $0
(the portion following the final slash)
\t the current time in 24-hour HH:MM:SS format
\T the current time in 12-hour HH:MM:SS format
\@ the current time in 12-hour am/pm format
\u the username of the current user
\v the version of bash (e.g., 2.00)
\V the release of bash, version + patchlevel
(e.g., 2.00.0)
\w the current working directory
\W the basename of the current working direcÂ
tory
\! the history number of this command
\# the command number of this command
\$ if the effective UID is 0, a #, otherwise a
$
\nnn the character corresponding to the octal
number nnn
\\ a backslash
\[ begin a sequence of non-printing characters,
which could be used to embed a terminal con
trol sequence into the prompt
\] end a sequence of non-printing characters
Basic escape sequences are pretty nice and Bash is feature rich with them. For example look at the three different time formats:
\t the current time in 24-hour HH:MM:SS format \T the current time in 12-hour HH:MM:SS format \@ the current time in 12-hour am/pm format
Just by default the bash prompt can be very informative but what if something a little bit more is needed?
As noted in the Bash Prompt
HOWTO commands can be executed every time the
RETURN sequence is sent to the shell interpreter. For
this example the Bash Prompt HOWTO provides ample
demonstration of some commands:
#!/bin/bash
# lsbytesum - sum the number of bytes in a directory listing
TotalBytes=0
for Bytes in $(ls -l | grep "^-" | awk '{ print $5 }')
do
let TotalBytes=$TotalBytes+$Bytes
done
TotalMeg=$(echo -e "scale=3 \n$TotalBytes/1048576 \nquit" | bc)
echo -n "$TotalMeg"
will yield the results in the author's directory of:
[2158][giles@nikola:~]$ PS1="[\u@\h:\w (\$(lsbytesum) Mb)]\$ " [giles@nikola:~ (0 Mb)]$ cd /bin [giles@nikola:/bin (4.498 Mb)]$
Pretty neat stuff. The bashrc can also
contain functions that are used in the prompt itself.
XTermsbashrcEntire functions can be put right into the .bashrc
file for similar command processing. Following is an example
function:
rand_titles ()
{
if [ $TERM = xterm ]; then
TLINES=`wc -l $HOME/.xterm_titles | awk '{print $1;}'`
TLINE=$[ ${RANDOM} % $TLINES ];
TLINE=$[$TLINE + 1];
TITLE=`head -$TLINE < $HOME/.xterm_titles | tail -1`
echo -ne "\033]0;${TITLE}\007"
fi
}
.xterm_titles
file.RANDOM environment variable to calculate a
random number within the TLINES range. Assign said
number directly to TLINETLINE.TLINE extract a line from
.xterm_titles and assign it to
TITLE.TITLE
variable).Essentially rand_titles just picks a random line
out of a file and feeds to the current xterm program
as a new title.
Not as difficult as it would seem; the call is just slid right into the prompt command itself:
PROMPT_COMMAND='rand_titles'
Essentially - any Unix software that can receive data from a pipe can be affected by bash prompt functions.
The text would be remiss no credit was given where due. I
originally figured all of this out by downloading Carsten Haitzler's
(aka Rasterman) files section [2].
Ironically the example used was for the Z shell zsh [ 3 ] so there was a little translating going on.
Be Warned! messing with the prompt, especially if you are inserting entire functions into it can be dangerous. If you do not have administrator access (as root or some delegated role) to the system then there are a few things to consider.
Often, power users are allowed to request test accounts. If playing with functions built into prompts is on the agenda then do so. Get a test account that can be switch-user'd to for testing.
bashrcOne of the nice things about bash is that the
bashrc can be resourced on the fly for testing.
Basically take the following steps to make sure that the original
bashrc can be restored in case of a mistake:
cd $HOMEcp .bashrc .bashrc.ORIGChanges can be experimented with by simply sourcing the changed
bashrc:
source .bashrc
Note that a current bashrc can also just be copied to a
new one, then source the test bashrc to see
if there are any problems:
cp .bashrc bashtest (makemany changes...) source bashtest... ... pray2 $DEITY
Test functions before inclusion in the prompt. If a system has a
lot of NFS mounts then do not include a global
df command in the prompt [5]. Keep
things like how much will this cost and can it hang?
in mind
when dealing with prompt commands.
Customizing and mastering the Unix shell environment can make for not just a pleasant experience as a user but a practical experience for users.
zsh has given me serious reason to think about trading
off shells for awhile even just for fun.df output in every user's
login files.