Found this on the net. Older, but lots of info
Bash Prompt HOWTO
Giles Orr,
giles@interlog.com v0.76 31 December 1999
Creating and controlling terminal and xterm prompts is discussed,
including incorporating standard escape sequences to give username,
current working directory, time, etc. Further suggestions are made on
how to modify xterm title bars, use external functions to provide
prompt information, and how to use ANSI colours.
______________________________________________________________________
Table of Contents
1. Introduction and Administrivia
1.1 Requirements
1.2 How To Use This Document
1.3 Translations
1.4 Problems
1.5 Send Me Comments and Suggestions
1.6 Credits
1.7 Copyright and Disclaimer
2. Bash and Bash Prompts
2.1 What is Bash?
2.2 What Can Tweaking Your Bash Prompt Do For You?
2.3 Why Bother?
2.4 The First Step
2.5 Bash Prompt Escape Sequences
2.6 Setting the PS? Strings Permanently
3. Bash Programming and Shell Scripts
3.1 Variables
3.2 Quotes and Special Characters
3.3 Command Substitution
3.4 Non-Printing Characters in Prompts
3.5 Sourcing a File
3.6 Functions, Aliases, and the Environment
4. External Commands
4.1 PROMPT_COMMAND
4.2 External Commands in the Prompt
4.3 What to Put in Your Prompt
5. Xterm Title Bar Manipulations
6. ANSI Escape Sequences: Colours and Cursor Movement
6.1 Colours
6.2 Cursor Movement
6.3 Moving the Cursor With tput
7. Special Characters: Octal Escape Sequences
8. The Bash Prompt Package
8.1 Availability
8.2 Xterm Fonts
8.3 Changing the Xterm Font
9. Loading a Different Prompt
9.1 Loading a Different Prompt, Later
9.2 Loading a Different Prompt, Immediately
10. Loading Prompt Colours Dynamically
10.1 A "Proof of Concept" Example
11. Prompt Code Snippets
11.1 Built-in Escape Sequences
11.2 Date and Time
11.3 Counting Files in the Current Directory
11.4 Total Bytes in the Current Directory
11.5 Checking the Current TTY
11.6 Suspended Job Count
11.7 Uptime and Load
11.8 Number of Processes
11.9 Controlling the Width of $PWD
11.10 Laptop Power
11.11 Having the Prompt Ignored on Cut and Paste
11.12 Setting the Window Title and Icon Title Separately
12. Example Prompts
12.1 Examples on the Web Over time, many people have e-mailed me excellent examples, and I've written some interesting ones myself. There are far too many to include here, so I have put all of the examples together into some web pages which can be seen at
12.2 A "Lightweight" Prompt
12.3 Elite from Bashprompt Themes
12.4 A "Power User" Prompt
12.5 Prompt Depending on Connection Type
12.6 A Prompt the Width of Your Term
12.7 The Elegant Useless Clock Prompt
______________________________________________________________________
1. Introduction and Administrivia
1.1. Requirements
You will need Bash. The default version for most distributions is
either 1.14.7, or 2.0.x. 1.14.7 was the standard for years, but is
slowly being replaced. I've been using Bash 2.0.x for quite a while
now, but almost all code presented here should work under 1.14.7. If
I'm aware of a problem, I'll mention it. You can check your Bash
version by typing echo $BASH_VERSION at the prompt. On my machine, it
responds with 2.03.6(1)-release.
Shell programming experience would be good, but isn't essential: the
more you know, the more complex the prompts you'll be able to create.
I assume a basic knowledge of shell programming and Unix utilities as
I go through this tutorial. However, my own shell programming skills
are limited, so I give a lot of examples and explanation that may
appear unnecessary to an experienced shell programmer.
1.2. How To Use This Document
I include a lot of examples and explanatory text. Different parts
will be of varying usefulness to different people. This has grown
long enough that reading it straight through would be difficult - just
read the sections you need, backtrack as necessary.
1.3. Translations
Japanese:
http://www.jf.linux.or.jp/JF/JF-ftp/other-formats/Bash- Prompt/Bash-Prompt-HOWTO.html, provided by Akira Endo,
akendo@t3.rim.or.jp.
German: translation is in progress by Thomas Keil, thomas@h-
preissler.de.
Italian: by Daniel Dui,
ddui@iee.org, available at
http://www.crs4.it/~dui/linux.html.
Portugese: translation is in progress by Mrio Gamito,
mario.gamito@mail.telepac.pt.
Spanish: translation by Iosu Santurtn
iosu@bigfoot.com at
http://mipagina.euskaltel.es/iosus/linu ... HOWTO.html.
Dutch: translation is in progress by Ellen Bokhorst
elboh@gironet.nl,
and it will be available at
http://www.nl.linux.org/doc/HOWTO.
Chinese: translation in progress by Allen Huang
lancelot@tomail.com.tw. I will include a URL when I have it.
Many thanks to all of them! URLs will be included as they're
available.
If you are working on a translation, please notify me - especially if
it's available at a linkable URL. Thanks.
1.4. Problems
This is a list of problems I've noticed while programming prompts.
Don't start reading here, and don't let this list discourage you -
these are mostly quite minor details. Just check back if you run into
anything odd.
o Many Bash features (such as math within $(()) among others) are
compile time options. If you're using a binary distribution such
as comes with a standard Linux distribution, all such features
should be compiled in. But if you're working on someone else's
system, this is worth keeping in mind if something you expected to
work doesn't. Some notes about this in Learning the Bash Shell,
p.260-262.
o The terminal screen manager "screen" doesn't always get along with
ANSI colours. I'm not a screen expert, unfortunately. My current
version of screen (3.7.6-1, an RPM package) seems to work well in
all cases, but I've seen occasions where screen reduced all prompt
colours to the standard foreground colour in X terminals. This
doesn't appear to be a problem on the console.
o Xdefaults files can override colours. Look in ~/.Xdefaults for
lines referring to XTerm*background and XTerm*foreground (or
possibly XTerm*Background and XTerm*Foreground).
o One of the prompts mentioned in this document uses the output of
"jobs" - as discussed at that time, "jobs" output to a pipe is
broken in Bash 2.02.
o ANSI cursor movement escape sequences aren't all implemented in all
X terminals. That's discussed in its own section.
o Some nice looking pseudo-graphics can be created by using a VGA
font rather than standard Linux fonts. Unfortunately, these
effects look awful if you don't use a VGA font, and there's no way
to detect within a term what kind of font it's using.
o Bash 2.0+ is out, and it incorporates some new features, and
changes some behaviour. Things that work under 1.14.7 don't
necessarily work the same under 2.0+, or vice versa.
1.5. Send Me Comments and Suggestions
This is a learning experience for me. I've come to know a fair bit
about what can be done to create interesting and useful Bash Prompts,
but I need your input to correct and improve this document. I've
tried to check suggestions I make against different versions of Bash
(2.0x and 1.14.7), but let me know of any incompatibilities you find.
The latest version of this document should always be available at
http://www.interlog.com/~giles/bashprompt/. Please check this out,
and feel free to e-mail me at
giles@interlog.com with suggestions.
I use the Linux Documentation Project HOWTOs almost exclusively in the
HTML format, so when I convert this from SGML (its native format),
HTML is the only format I check thoroughly. If there are problems
with other formats, I may not know about them, and I'd appreciate a
note about them.
1.6. Credits
In producing this document, I have borrowed heavily from the work of
the Bashprompt project at
http://bash.current.nu/. Other sources used
include the xterm Title mini-HOWTO by Ric Lister, available at
http://sunsite.unc.edu/LDP/HOWTO/mini/Xterm-Title.html, Ansi Prompts
by Keebler, available at
http://www.ncal.verio.com/~keebler/ansi.html,
How to make a Bash Prompt Theme by Stephen Webb, available at
http://bash.current.nu/bash/HOWTO.html, and X ANSI Fonts by Stumpy,
available at
http://home.earthlink.net/~us5zahns/enl/ansifont.html.
Also of immense help were several conversations and e-mails from Dan,
an ex-co-worker at Georgia College & State University, whose knowledge
of Unix far exceeds mine. He's given me several excellent
suggestions, and ideas of his have led to some interesting prompts.
Three books that have been very useful while programming prompts are
Linux in a Nutshell by Jessica Heckman Perry (O'Reilly, 1997),
Learning the Bash Shell by Cameron Newham and Bill Rosenblatt
(O'Reilly, 2nd. ed., 1998) and Unix Shell Programming by Lowell Jay
Arthur (Wiley, 1986. This is the first edition, the fourth came out
in 1997).
1.7. Copyright and Disclaimer
This document is copyright 1998-1999 by Giles Orr. You are encouraged
to redistribute it. You may not modify this document (see the section
on contacting me: I incorporate most changes recommended by readers).
Please contact me if you're interested in doing a translation.
This document is available for free, and, while I have done the best I
can to make it accurate and up to date, I take no responsibility for
any problems you may encounter resulting from the use of this
document.
2. Bash and Bash Prompts
2.1. What is Bash?
Descended from the Bourne Shell, Bash is a GNU product, the "Bourne
Again SHell." It's the standard command line interface on most Linux
machines. It excels at interactivity, supporting command line
editing, completion, and recall. It also supports configurable
prompts - most people realize this, but don't know how much can be
done.
2.2. What Can Tweaking Your Bash Prompt Do For You?
Most Linux systems have a default prompt in one colour (usually gray)
that tells you your user name, the name of the machine you're working
on, and some indication of your current working directory. This is
all useful information, but you can do much more with the prompt: all
sorts of information can be displayed (tty number, time, date, load,
number of users, uptime ...) and the prompt can use ANSI colours,
either to make it look interesting, or to make certain information
stand out. You can also manipulate the title bar of an Xterm to
reflect some of this information.
2.3. Why Bother?
Beyond looking cool, it's often useful to keep track of system
information. One idea that I know appeals to some people is that it
makes it possible to put prompts on different machines in different
colours. If you have several Xterms open on several different
machines, or if you tend to forget what machine you're working on and
delete the wrong files (or shut down the server instead of the
workstation), you'll find this a great way to remember what machine
you're on.
For myself, I like the utility of having information about my machine
and work environment available all the time. And I like the challenge
of trying to figure out how to put the maximum amount of information
into the smallest possible space while maintaining readability.
2.4. The First Step
The appearance of the prompt is governed by the shell variable PS1.
Command continuations are indicated by the PS2 string, which can be
modified in exactly the same ways discussed here - since controlling
it is exactly the same, and it isn't as "interesting," I'll mostly be
modifying the PS1 string. (There are also PS3 and PS4 strings. These
are never seen by the average user - see the Bash man page if you're
interested in their purpose.) To change the way the prompt looks, you
change the PS1 variable. For experimentation purposes, you can enter
the PS1 strings directly at the prompt, and see the results
immediately (this only affects your current session, and the changes
go away when you log out). If you want to make a change to the prompt
permanent, look at the section below ``Setting the PS? Strings
Permanently''.
Before we get started, it's important to remember that the PS1 string
is stored in the environment like any other environment variable. If
you modify it at the command line, your prompt will change. Before
you make any changes, you can save your current prompt to another
environment variable:
[giles@nikola giles]$ SAVE=$PS1
[giles@nikola giles]$
The simplest prompt would be a single character, such as:
[giles@nikola giles]$ PS1=$
$ls
bin mail
$
This demonstrates the best way to experiment with basic prompts,
entering them at the command line. Notice that the text entered by
the user appears immediately after the prompt: I prefer to use
$PS1="$ "
$ ls
bin mail
$
which forces a space after the prompt, making it more readable. To
restore your original prompt, just call up the variable you stored:
$ PS1=$SAVE
[giles@nikola giles]$
2.5. Bash Prompt Escape Sequences
There are a lot of escape sequences offered by the Bash shell for
insertion in the prompt. From the Bash 2.02 man page:
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
\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
Continuing where we left off:
[giles@nikola giles]$ PS1="\u@\h \W> "
giles@nikola giles> ls
bin mail
giles@nikola giles>
This is similar to the default on most Linux distributions. I wanted
a slightly different appearance, so I changed this to:
giles@nikola giles> PS1="[\t][\u@\h:\w]\$ "
[21:52:01][giles@nikola:~]$ ls
bin mail
[21:52:15][giles@nikola:~]$
2.6. Setting the PS? Strings Permanently
Various people and distributions set their PS? strings in different
places. The most common places are /etc/profile, /etc/bashrc,
~/.bash_profile, and ~/.bashrc . Johan Kullstam (
johan19@idt.net)
writes:
the PS1 string should be set in .bashrc. this is because
non-interactive bashes go out of their way to unset PS1.
the bash man page tells how the presence or absence of PS1
is a good way of knowing whether one is in an interactive vs
non-interactive (ie script) bash session.
the way i realized this is that startx is a bash script.
what this means is, startx will wipe out your prompt. when
you set PS1 in .profile (or .bash_profile), login at
console, fire up X via startx, your PS1 gets nuked in the
process leaving you with the default prompt.
one workaround is to launch xterms and rxvts with the -ls
option to force them to read .profile. but any time a shell
is called via a non-interactive shell-script middleman PS1
is lost. system(3) uses sh -c which if sh is bash will kill
PS1. a better way is to place the PS1 definition in
.bashrc. this is read every time bash starts and is where
interactive things - eg PS1 should go.
therefore it should be stressed that PS1=..blah.. should be
in .bashrc and not .profile.
I tried to duplicate the problem he explains, and encountered a
different one: my PROMPT_COMMAND variable (which will be introduced
later) was blown away. My knowledge in this area is somewhat shaky,
so I'm going to go with what Johan says.
3. Bash Programming and Shell Scripts
3.1. Variables
I'm not going to try to explain all the details of Bash scripting in a
section of this HOWTO, just the details pertaining to prompts. If you
want to know more about shell programming and Bash in general, I
highly recommend Learning the Bash Shell by Cameron Newham and Bill
Rosenblatt (O'Reilly, 1998). Oddly, my copy of this book is quite
frayed. Again, I'm going to assume that you know a fair bit about
Bash already. You can skip this section if you're only looking for
the basics, but remember it and refer back if you proceed much
farther.
Variables in Bash are assigned much as they are in any programming
language:
testvar=5
foo=zen
bar="bash prompt"
Quotes are only needed in an assignment if a space (or special
character, discussed shortly) is a part of the variable.
Variables are referenced slightly differently than they are assigned:
> echo $testvar
5
> echo $foo
zen
> echo ${bar}
bash prompt
> echo $NotAssigned
>
A variable can be referred to as $bar or ${bar}. The braces are
useful when it is unclear what is being referenced: if I write $barley
do I mean ${bar}ley or ${barley}? Note also that referencing a value
that hasn't been assigned doesn't generate an error, instead returning
nothing.
3.2. Quotes and Special Characters
If you wish to include a special character in a variable, you will
have to quote it differently:
> newvar=$testvar
> echo $newvar
5
> newvar="$testvar"
> echo $newvar
5
> newvar='$testvar'
> echo $newvar
$testvar
> newvar=\$testvar
> echo $newvar
$testvar
>
The dollar sign isn't the only character that's special to the Bash
shell, but it's a simple example. An interesting step we can take to
make use of assigning a variable name to another variable name is to
use eval to dereference the stored variable name:
> echo $testvar
5
> echo $newvar
$testvar
> eval echo $newvar
5
>
Normally, the shell does only one round of substitutions on the
expression it is evaluating: if you say echo $newvar the shell will
only go so far as to determine that $newvar is equal to the text
string $testvar, it won't evaluate what $testvar is equal to. eval
forces that evaluation.
3.3. Command Substitution
In almost all cases in this document, I use the $(<command>)
convention for command substitution: that is,
$(date +%H%M)
means "substitute the output from the date +%H%M command here." This
works in Bash 2.0+. In some older versions of Bash, prior to 1.14.7,
you may need to use backquotes (`date +%H%M`). Backquotes can be used
in Bash 2.0+, but are being phased out in favor of $(), which nests
better. If you're using an earlier version of Bash, you can usually
substitute backquotes where you see $(). If the command substitution
is escaped (ie. \$(command) ), then use backslashes to escape BOTH
your backquotes (ie. \'command\' ).
3.4. Non-Printing Characters in Prompts
Many of the changes that can be made to Bash prompts that are
discussed in this HOWTO use non-printing characters. Changing the
colour of the prompt text, changing an Xterm title bar, and moving the
cursor position all require non-printing characters.
If I want a very simple prompt consisting of a greater-than sign and a
space:
[giles@nikola giles]$ PS1='> '
>
This is just a two character prompt. If I modify it so that it's a
bright yellow greater-than sign (colours are discussed in their own
section):
> PS1='\033[1;33m>\033[0m '
>
This works fine - until you type in a large command line. Because the
prompt still only consists of two printing characters (a greater-than
sign and a space) but the shell thinks that this prompt is eleven
characters long (I think it counts '\033' , '[1' and '[0' as one
character each). You can see this by typing a really long command
line - you will find that the shell wraps the text before it gets to
the edge of the terminal, and in most cases wraps it badly. This is
because it's confused about the actual length of the prompt.
So use this instead:
> PS1='\[\033[1;33m\]>\[\033[0m\] '
This is more complex, but it works. Command lines wrap properly.
What's been done is to enclose the '\033[1;33m' that starts the yellow
colour in square brackets, including the brackets themselves, is a
non-printing character." The same is done with the '\033[0m' that
ends the colour.
3.5. Sourcing a File
When a file is sourced (by typing either source filename or .
filename at the command line), the lines of code in the file are
executed as if they were printed at the command line. This is
particularly useful with complex prompts, to allow them to be stored
in files and called up by sourcing the file they are in.
In examples, you will find that I often include #!/bin/bash at the
beginning of files including functions. This is not necessary if you
are sourcing a file, just as it isn't necessary to chmod +x a file
that is going to be sourced. I do this because it makes Vim (my
editor of choice, no flames please - you use what you like) think I'm
editing a shell script and turn on colour syntax highlighting.
3.6. Functions, Aliases, and the Environment
As mentioned earlier, PS1, PS2, PS3, PS4, and PROMPT_COMMAND are all
stored in the Bash environment. For those of us coming from a DOS
background, the idea of tossing big hunks of code into the environment
is horrifying, because that DOS environment was small, and didn't
exactly grow well. There are probably practical limits to what you
can and should put in the environment, but I don't know what they are,
and we're probably talking a couple of orders of magnitude larger than
what DOS users are used to. As Dan put it:
"In my interactive shell I have 62 aliases and 25 functions. My rule
of thumb is that if I need something solely for interactive use and
can handily write it in bash I make it a shell function (assuming it
can't be easily expressed as an alias). If these people are worried
about memory they don't need to be using bash. Bash is one of the
largest programs I run on my linux box (outside of Oracle). Run top
sometime and press 'M' to sort by memory - see how close bash is to
the top of the list. Heck, it's bigger than sendmail! Tell 'em to go
get ash or something."
I guess he was using console only the day he tried that: running X and
X apps, I have a lot of stuff larger than Bash. But the idea is the
same: the environment is something to be used, and don't worry about
overfilling it.
I risk censure by Unix gurus when I say this (for the crime of over-
simplification), but functions are basically small shell scripts that
are loaded into the environment for the purpose of efficiency.
Quoting Dan again: "Shell functions are about as efficient as they can
be. It is the approximate equivalent of sourcing a bash/bourne shell
script save that no file I/O need be done as the function is already
in memory. The shell functions are typically loaded from [.bashrc or
.bash_profile] depending on whether you want them only in the initial
shell or in subshells as well. Contrast this with running a shell
script: Your shell forks, the child does an exec, potentially the path
is searched, the kernel opens the file and examines enough bytes to
determine how to run the file, in the case of a shell script a shell
must be started with the name of the script as its argument, the shell
then opens the file, reads it and executes the statements. Compared
to a shell function, everything other than executing the statements
can be considered unnecessary overhead."
Aliases are simple to create:
alias d="ls --color=tty --classify"
alias v="d --format=long"
alias rm="rm -i"
Any arguments you pass to the alias are passed to the command line of
the aliased command (ls in the first two cases). Note that aliases
can be nested, and they can be used to make a normal unix command
behave in a different way. (I agree with the argument that you
shouldn't use the latter kind of aliases - if you get in the habit of
relying on "rm *" to ask you if you're sure, you may lose important
files on a system that doesn't use your alias.)
Functions are used for more complex program structures. As a general
rule, use an alias for anything that can be done in one line.
Functions differ from shell scripts in that they are loaded into the
environment so that they work more quickly. As a general rule again,
you would want to keep functions relatively small, and any shell
script that gets relatively large should remain a shell script rather
than turning it into a function. Your decision to load something as a
function is also going to depend on how often you use it. If you use
a small shell script infrequently, leave it as a shell script. If you
use it often, turn it into a function.
To modify the behaviour of ls, you could do something like the
following:
function lf
{
ls --color=tty --classify $*
echo "$(ls -l $* | wc -l) files"
}
This could readily be set as an alias, but for the sake of example,
we'll make it a function. If you type the text shown into a text file
and then source that file, the function will be in your environment,
and be immediately available at the command line without the overhead
of a shell script mentioned previously. The usefulness of this
becomes more obvious if you consider adding more functionality to the
above function, such as using an if statement to execute some special
code when links are found in the listing.
4. External Commands
4.1. PROMPT_COMMAND
Bash provides another environment variable called PROMPT_COMMAND. The
contents of this variable are executed as a regular Bash command just
before Bash displays a prompt.
[21:55:01][giles@nikola:~] PS1="[\u@\h:\w]\$ "
[giles@nikola:~] PROMPT_COMMAND="date +%H%M"
2155
[giles@nikola:~] d
bin mail
2156
[giles@nikola:~]
What happened above was that I changed PS1 to no longer include the \t
escape sequence, so the time was no longer a part of the prompt. Then
I used date +%H%M to display the time in a format I like better. But
it appears on a different line than the prompt. Tidying this up using
echo -n ... as shown below works with Bash 2.0+, but appears not to
work with Bash 1.14.7: apparently the prompt is drawn in a different
way, and the following method results in overlapping text.
2156
[giles@nikola:~] PROMPT_COMMAND="echo -n [$(date +%H%M)]"
[2156][giles@nikola:~]$
[2156][giles@nikola:~]$ d
bin mail
[2157][giles@nikola:~]$ unset PROMPT_COMMAND
[giles@nikola:~]
echo -n ... controls the output of the date command and supresses the
trailing newline, allowing the prompt to appear all on one line. At
the end, I used the unset command to remove the PROMPT_COMMAND
environment variable.
4.2. External Commands in the Prompt
You can use the output of regular Linux commands directly in the
prompt as well. Obviously, you don't want to insert a lot of
material, or it will create a large prompt. You also want to use a
fast command, because it's going to be executed every time your prompt
appears on the screen, and delays in the appearance of your prompt
while you're working can be very annoying. (Unlike the previous
example that this closely resembles, this does work with Bash 1.14.7.)
[21:58:33][giles@nikola:~]$ PS1="[\$(date +%H%M)][\u@\h:\w]\$ "
[2159][giles@nikola:~]$ ls
bin mail
[2200][giles@nikola:~]$
It's important to notice the backslash before the dollar sign of the
command substitution. Without it, the external command is executed
exactly once: when the PS1 string is read into the environment. For
this prompt, that would mean that it would display the same time no
matter how long the prompt was used. The backslash protects the
contents of $() from immediate shell interpretation, so "date" is
called every time a prompt is generated.
Linux comes with a lot of small utility programs like date, grep, or
wc that allow you to manipulate data. If you find yourself trying to
create complex combinations of these programs within a prompt, it may
be easier to make an alias, function, or shell script of your own, and
call it from the prompt. Escape sequences are often required in bash
shell scripts to ensure that shell variables are expanded at the
correct time (as seen above with the date command): this is raised to
another level within the prompt PS1 line, and avoiding it by creating
functions is a good idea.
An example of a small shell script used within a prompt is given
below:
______________________________________________________________________
#!/bin/bash
# lsbytesum - sum the number of bytes in a directory listing
TotalBytes=0
for Bytes in $(ls -l | grep "^-" | cut -c30-41)
do
let TotalBytes=$TotalBytes+$Bytes
done
TotalMeg=$(echo -e "scale=3 \n$TotalBytes/1048576 \nquit" | bc)
echo -n "$TotalMeg"
______________________________________________________________________
I have at times kept this both as a function, or as a shell script in
my ~/bin directory, which is on my path. Used in a prompt:
[2158][giles@nikola:~]$ PS1="[\u@\h:\w (\$(lsbytesum) Mb)]\$ "
[giles@nikola:~ (0 Mb)]$ cd /bin
[giles@nikola:/bin (4.498 Mb)]$
4.3. What to Put in Your Prompt
You'll find I put username, machine name, time, and current directory
name in most of my prompts. With the exception of the time, these are
very standard items to find in a prompt, and time is probably the next
most common addition. But what you include is entirely a matter of
personal taste. Here are examples from people I know to help give you
ideas.
Dan's prompt is minimal but very effective, particularly for the way
he works.
[giles@nikola:~]$ cur_tty=$(tty | sed -e "s/.*tty\(.*\)/\1/")
[giles@nikola:~]$ echo $cur_tty
p4
[giles@nikola:~]$ PS1="\!,$cur_tty,\$?\$ "
1095,p4,0$
Dan doesn't like that having the current working directory can resize
the prompt drastically as you move through the directory tree, so he
keeps track of that in his head (or types "pwd"). He learned Unix
with csh and tcsh, so he uses his command history extensively
(something many of us weened on Bash do not do), so the first item in
the prompt is the history number. The second item is the significant
characters of the tty (the output of "tty" is cropped with sed), an
item that can be useful to "screen" users. The third item is the exit
value of the last command/pipeline (note that this is rendered useless
by any command executed within the prompt - you could work around that
by capturing it to a variable and playing it back, though). Finally,
the "\$" is a dollar sign for a regular user, and switches to a hash
mark ("#") if the user is root.
Torben Fjerdingstad (
tfj@fjerdingstad.dk) wrote to tell me that he
often suspends jobs and then forgets about them. He uses his prompt
to remind himself of suspended jobs:
[giles@nikola:~]$ function jobcount {
> jobs|wc -l| awk '{print $1}'
> }
[giles@nikola:~]$ export PS1='\W[`jobcount`]# '
giles[0]# man ls &
[1] 4150
[1]+ Stopped (tty output) man ls
giles[1]#
Torben uses awk to trim the whitespace from the output of wc, while I
would have used sed or tr - not because they're better, but because
I'm more familiar with them. There are probably other ways as well.
Torben also surrounds his PS1 string in single quotes, which prevent
Bash from immediately interpreting the backquotes, so he doesn't have
to escape them as I have mentioned.
NOTE: There is a known bug in Bash 2.02 that causes the jobs command
(a shell builtin) to return nothing to a pipe. If you try the above
under Bash 2.02, you will always get a "0" back regardless of how many
jobs you have suspended. This problem is fixed in 2.03.
5. Xterm Title Bar Manipulations
Non-printing escape sequences can be used to produce interesting
effects in prompts. To use these escape sequences, you need to
enclose them in \[ and \] (as discussed in ``Non-Printing Characters
in Prompts''), telling Bash to ignore this material while calculating
the size of the prompt. Failing to include these delimiters results
in line editing code placing the cursor incorrectly because it doesn't
know the actual size of the prompt. Escape sequences must also be
preceded by \033[ in Bash prior to version 2, or by either \033[ or
\e[ in later versions.
If you try to change the title bar of your Xterm with your prompt when
you're at the console, you'll produce garbage in your prompt. To
avoid this, test the TERM environment variable to tell if your prompt
is going to be in an Xterm.
______________________________________________________________________
function proml
{
case $TERM in
xterm*)
local TITLEBAR='\[\033]0;\u@\h:\w\007\]'
;;
*)
local TITLEBAR=''
;;
esac
PS1="${TITLEBAR}\
[\$(date +%H%M)]\
[\u@\h:\w]\
\$ "
PS2='> '
PS4='+ '
}
______________________________________________________________________
This is a function that can be incorporated into ~/.bashrc. The
function name could then be called to execute the function. The
function, like the PS1 string, is stored in the environment. Once the
PS1 string is set by the function, you can remove the function from
the environment with unset proml. Since the prompt can't change from
being in an Xterm to being at the console, the TERM variable isn't
tested every time the prompt is generated. I used continuation
markers (backslashes) in the definition of the prompt, to allow it to
be continued on multiple lines. This improves readability, making it
easier to modify and debug.
I define this as a function because this is how the Bashprompt package
(discussed later in this document: ``The Bash Prompt Package'') deals
with prompts: it's not the only way to do it, but it works well. As
the prompts you use become more complex, it becomes more and more
cumbersome to type them in at the prompt, and more practical to make
them into some sort of text file. In this case, to test this at the
prompt, save the above as a text file called "proml". You can work
with it as follows:
[giles@nikola:/bin (4.498 Mb)]$ cd -> Go where you want to save the prompt
[giles@nikola:~ (0 Mb)]$ vi proml -> Edit the prompt file
... -> Enter the text given above
[giles@nikola:~ (0 Mb)]$ source proml -> Read the prompt function
[giles@nikola:~ (0 Mb)]$ proml -> Execute the prompt function
The first step in creating this prompt is to test if the shell we're
starting is an xterm or not: if it is, the shell variable
(${TITLEBAR}) is defined. It consists of the appropriate escape
sequences, and \u@\h:\w, which puts <user>@<machine>:<working
directory> in the Xterm title bar. This is particularly useful with
minimized Xterms, making them more rapidly identifiable. The other
material in this prompt should be familiar from previous prompts we've
created.
The only drawback to manipulating the Xterm title bar like this occurs
when you log into a system on which you haven't set up the title bar
hack: the Xterm will continue to show the information from the
previous system that had the title bar hack in place.
6. ANSI Escape Sequences: Colours and Cursor Movement
6.1. Colours
As mentioned before, non-printing escape sequences have to be enclosed
in \[\033[ and \]. For colour escape sequences, they should also be
followed by a lowercase m.
If you try out the following prompts in an xterm and find that you
aren't seeing the colours named, check out your ~/.Xdefaults file (and
possibly its bretheren) for lines like "XTerm*Foreground:
BlanchedAlmond". This can be commented out by placing an exclamation
mark ("!") in front of it. Of course, this will also be dependent on
what terminal emulator you're using. This is the likeliest place that
your term foreground colours would be overridden.
To include blue text in the prompt:
PS1="\[\033[34m\][\$(date +%H%M)][\u@\h:\w]$ "
The problem with this prompt is that the blue colour that starts with
the 34 colour code is never switched back to the regular colour, so
any text you type after the prompt is still in the colour of the
prompt. This is also a dark shade of blue, so combining it with the
bold code might help:
PS1="\[\033[1;34m\][\$(date +%H%M)][\u@\h:\w]$\[\033[0m\] "
The prompt is now in light blue, and it ends by switching the colour
back to nothing (whatever foreground colour you had previously).
Here are the rest of the colour equivalences:
Black 0;30 Dark Gray 1;30
Blue 0;34 Light Blue 1;34
Green 0;32 Light Green 1;32
Cyan 0;36 Light Cyan 1;36
Red 0;31 Light Red 1;31
Purple 0;35 Light Purple 1;35
Brown 0;33 Yellow 1;33
Light Gray 0;37 White 1;37
Daniel Dui (
ddui@iee.org) points out that to be strictly accurate, we
must mention that the list above is for colours at the console. In an
xterm, the code 1;31 isn't "Light Red," but "Bold Red." This is true
of all the colours.
You can also set background colours by using 44 for Blue background,
41 for a Red background, etc. There are no bold background colours.
Combinations can be used, like Light Red text on a Blue background:
\[\033[44;1;31m\], although setting the colours separately seems to
work better (ie. \[\033[44m\]\[\033[1;31m\]). Other codes available
include 4: Underscore, 5: Blink, 7: Inverse, and 8: Concealed.
Aside: Many people (myself included) object strongly to the "blink"
attribute. Fortunately, it doesn't work in any terminal emulators
that I'm aware of - but it will still work on the console. And, if
you were wondering (as I did) "What use is a 'Concealed' attribute?!"
- I saw it used in an example shell script (not a prompt) to allow
someone to type in a password without it being echoed to the screen.
Based on a prompt called "elite2" in the Bashprompt package (which I
have modified to work better on a standard console, rather than with
the special xterm fonts required to view the original properly), this
is a prompt I've used a lot:
______________________________________________________________________
function elite
{
local GRAY="\[\033[1;30m\]"
local LIGHT_GRAY="\[\033[0;37m\]"
local CYAN="\[\033[0;36m\]"
local LIGHT_CYAN="\[\033[1;36m\]"
case $TERM in
xterm*)
local TITLEBAR='\[\033]0;\u@\h:\w\007\]'
;;
*)
local TITLEBAR=""
;;
esac
local GRAD1=$(tty|cut -d/ -f3)
PS1="$TITLEBAR\
$GRAY-$CYAN-$LIGHT_CYAN(\
$CYAN\u$GRAY@$CYAN\h\
$LIGHT_CYAN)$CYAN-$LIGHT_CYAN(\
$CYAN\#$GRAY/$CYAN$GRAD1\
$LIGHT_CYAN)$CYAN-$LIGHT_CYAN(\
$CYAN\$(date +%H%M)$GRAY/$CYAN\$(date +%d-%b-%y)\
$LIGHT_CYAN)$CYAN-$GRAY-\
$LIGHT_GRAY\n\
$GRAY-$CYAN-$LIGHT_CYAN(\
$CYAN\$$GRAY:$CYAN\w\
$LIGHT_CYAN)$CYAN-$GRAY-$LIGHT_GRAY "
PS2="$LIGHT_CYAN-$CYAN-$GRAY-$LIGHT_GRAY "
}
______________________________________________________________________
I define the colours as temporary shell variables in the name of
readability. It's easier to work with. The "GRAD1" variable is a
check to determine what terminal you're on. Like the test to
determine if you're working in an Xterm, it only needs to be done
once. The prompt you see look like this, except in colour:
--(giles@nikola)-(75/ttyp7)-(1908/12-Oct-98)--
--($:~/tmp)--