mirror of https://github.com/tLDP/LDP
2322 lines
79 KiB
Plaintext
2322 lines
79 KiB
Plaintext
<!doctype linuxdoc system>
|
||
|
||
<article>
|
||
|
||
<title>Bash Prompt HOWTO
|
||
<author> Giles Orr,
|
||
<htmlurl url="mailto:giles@interlog.com" name="giles@interlog.com">
|
||
<date>v0.76 31 December 1999
|
||
|
||
<!-- CHANGELOG:
|
||
|
||
$Log$
|
||
Revision 0.76 1999/12/31 23:20:55 giles
|
||
Added Allen Huang, Chinese translator. Better tell him about it!
|
||
|
||
Revision 0.75 1999/12/19 23:23:40 giles
|
||
Changed Portugese translator to Mario Gamito.
|
||
|
||
Revision 0.74 1999/12/19 22:56:39 giles
|
||
Added Charles Lepple's code snippet for setting window title and icon
|
||
title separately.
|
||
|
||
Revision 0.73 1999/12/18 21:47:27 giles
|
||
Cleaned up tilde problem: Translators, note that I used a plain tilde
|
||
throughout, when I should have been using ˜ - I have substituted
|
||
in <p> tags, where it seems to matter, but not in htmlurls or tscreens.
|
||
This was badly needed: the HOWTO used to tell you to put stuff in your
|
||
/.bashrc , because the leading tilde simply didn't print ...
|
||
|
||
Revision 0.72 1999/12/18 21:27:48 giles
|
||
Added Rory Toma's code snippet for cutting and pasting prompts.
|
||
|
||
Revision 0.71 1999/12/18 20:30:51 giles
|
||
Several clean-ups, added "code snippet" on file size in current directory.
|
||
|
||
Revision 0.70 1999/07/29 12:59:25 giles
|
||
Added Ellen Bokhorst as Dutch translator.
|
||
|
||
Revision 0.69 1999/07/11 02:05:51 giles
|
||
Clean-up throughout document. Probably make translator's jobs much
|
||
more difficult by including many small changes. Sorry.
|
||
|
||
Revision 0.68 1999/07/10 21:04:38 giles
|
||
Major change: most material related to Bash programming is now in its
|
||
own section. The section is mostly complete (except for "sourcing a
|
||
file"), but I need to clean up the places I removed the material from.
|
||
|
||
Revision 0.BLAH Lost logs from 0.65-0.67 - somehow the leading dollar
|
||
sign before "Log" went missing, so logging wasn't done.
|
||
|
||
Revision 0.64 1999/06/06 02:48:36 giles
|
||
Added pointer to web examples in the Examples section.
|
||
|
||
Revision 0.63 1999/06/06 02:19:19 giles
|
||
Bunch of minor textual revisions, plus ...
|
||
Revised two or three of the examples to excise the embarrassing
|
||
$PWD trimming method and go for \{$cut\} instead ...
|
||
|
||
Revision 0.62 1999/03/23 12:20:24 giles
|
||
Added Bradley Alexander's bashrc in Examples.
|
||
|
||
Revision 0.61 1999/03/23 00:45:57 giles
|
||
Several changes, mostly cosmetic. Added Sergio's history of fonts.
|
||
|
||
-->
|
||
|
||
<abstract>
|
||
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.
|
||
</abstract>
|
||
|
||
<toc>
|
||
|
||
|
||
<!-- ****************************************************** -->
|
||
|
||
<sect>Introduction and Administrivia
|
||
|
||
<sect1>Requirements
|
||
|
||
<p>
|
||
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 <TT>echo
|
||
$BASH_VERSION</TT> at the prompt. On my machine, it responds with
|
||
<TT>2.03.6(1)-release</TT>.
|
||
|
||
<p>
|
||
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.
|
||
|
||
<sect1>How To Use This Document
|
||
|
||
<p>
|
||
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.
|
||
|
||
<sect1>Translations
|
||
|
||
<p>
|
||
<em>Japanese:</em> <htmlurl
|
||
url="http://www.jf.linux.or.jp/JF/JF-ftp/other-formats/Bash-Prompt/Bash-Prompt-HOWTO.html"
|
||
name="http://www.jf.linux.or.jp/JF/JF-ftp/other-formats/Bash-Prompt/Bash-Prompt-HOWTO.html">,
|
||
provided by Akira Endo, <htmlurl url="mailto:akendo@t3.rim.or.jp"
|
||
name="akendo@t3.rim.or.jp">.
|
||
|
||
<p>
|
||
<em>German:</em> translation is in progress by Thomas
|
||
Keil, <htmlurl url="mailto:thomas@h-preissler.de"
|
||
name="thomas@h-preissler.de">.
|
||
|
||
<p>
|
||
<em>Italian:</em> by Daniel Dui,
|
||
<htmlurl url="ddui@iee.org" name="ddui@iee.org">,
|
||
available at <htmlurl url="http://www.crs4.it/~dui/linux.html"
|
||
name="http://www.crs4.it/~dui/linux.html">.
|
||
|
||
<p>
|
||
<em>Portugese:</em> translation is in progress by M<>rio Gamito, <htmlurl
|
||
url="mario.gamito@mail.telepac.pt" name="mario.gamito@mail.telepac.pt">.
|
||
|
||
<!--
|
||
|
||
Until mid-October 1999, it was these guys. With their and my agreement,
|
||
M<EFBFBD>rio Gamito took over.
|
||
|
||
<em>Portugese:</em> translation is in progress by Augusto Cardoso <htmlurl
|
||
url="cardoso.a@mail.telepac.pt" name="cardoso.a@mail.telepac.pt"> and Pedro
|
||
Almeida <htmlurl url="palmeida@gemini.ci.uc.pt"
|
||
name="palmeida@gemini.ci.uc.pt">.
|
||
-->
|
||
|
||
<p>
|
||
<em>Spanish:</em> translation by Iosu Santurt<72>n <htmlurl
|
||
url="iosu@bigfoot.com" name="iosu@bigfoot.com"> at <htmlurl
|
||
url="http://mipagina.euskaltel.es/iosus/linux/Bash-Prompt-HOWTO.html"
|
||
name="http://mipagina.euskaltel.es/iosus/linux/Bash-Prompt-HOWTO.html">.
|
||
|
||
<p>
|
||
<em>Dutch:</em> translation is in progress by Ellen Bokhorst <htmlurl
|
||
url="elboh@gironet.nl" name="elboh@gironet.nl">, and it will be available
|
||
at <htmlurl url="http://www.nl.linux.org/doc/HOWTO"
|
||
name="http://www.nl.linux.org/doc/HOWTO">.
|
||
|
||
<p>
|
||
<em>Chinese:</em> translation in progress by Allen Huang <htmlurl
|
||
url="lancelot@tomail.com.tw" name="lancelot@tomail.com.tw">. I will
|
||
include a URL when I have it.
|
||
|
||
<p>
|
||
Many thanks to all of them! URLs will be included as they're available.
|
||
|
||
<p>
|
||
If you are working on a translation, please notify me - especially if it's
|
||
available at a linkable URL. Thanks.
|
||
|
||
<sect1>Problems
|
||
|
||
<p>
|
||
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.
|
||
|
||
<itemize>
|
||
|
||
<item>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 <em>Learning the Bash Shell</em>, p.260-262.
|
||
|
||
<item>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.
|
||
|
||
<item>Xdefaults files can override colours. Look in ˜/.Xdefaults for
|
||
lines referring to XTerm*background and XTerm*foreground (or possibly
|
||
XTerm*Background and XTerm*Foreground).
|
||
|
||
<item>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.
|
||
|
||
<item>ANSI cursor movement escape sequences aren't all implemented in all X
|
||
terminals. That's discussed in its own section.
|
||
|
||
<item>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.
|
||
|
||
<item>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.
|
||
|
||
</itemize>
|
||
|
||
<sect1>Send Me Comments and Suggestions
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
The latest version of
|
||
this document should always be available at
|
||
<htmlurl url="http://www.interlog.com/~giles/bashprompt/"
|
||
name="http://www.interlog.com/~giles/bashprompt/">. Please check this
|
||
out, and feel free to e-mail me at
|
||
<htmlurl url="mailto:giles@interlog.com" name="giles@interlog.com"> with
|
||
suggestions.
|
||
|
||
<p>
|
||
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.
|
||
|
||
<sect1>Credits
|
||
|
||
<p>
|
||
In producing this document, I have borrowed heavily from the work of
|
||
the Bashprompt project at
|
||
<htmlurl url="http://bash.current.nu/" name="http://bash.current.nu/">. Other
|
||
sources used include the <em>xterm Title mini-HOWTO</em> by
|
||
Ric Lister, available at
|
||
<htmlurl url="http://sunsite.unc.edu/LDP/HOWTO/mini/Xterm-Title.html"
|
||
name="http://sunsite.unc.edu/LDP/HOWTO/mini/Xterm-Title.html">,
|
||
<em>Ansi Prompts</em> by Keebler, available at
|
||
<htmlurl url="http://www.ncal.verio.com/~keebler/ansi.html"
|
||
name="http://www.ncal.verio.com/~keebler/ansi.html">, <em>How to make
|
||
a Bash Prompt Theme</em> by Stephen Webb, available at
|
||
<htmlurl url="http://bash.current.nu/bash/HOWTO.html"
|
||
name="http://bash.current.nu/bash/HOWTO.html">, and <em>X ANSI Fonts</em>
|
||
by Stumpy, available at
|
||
<htmlurl url="http://home.earthlink.net/~us5zahns/enl/ansifont.html"
|
||
name="http://home.earthlink.net/~us5zahns/enl/ansifont.html">.
|
||
|
||
<p>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.
|
||
|
||
<p>
|
||
Three books that have been very useful while programming prompts are
|
||
<em>Linux in a Nutshell</em> by Jessica Heckman Perry (O'Reilly, 1997),
|
||
<em>Learning the Bash Shell</em> by Cameron Newham and Bill Rosenblatt
|
||
(O'Reilly, 2nd. ed., 1998) and <em>Unix Shell Programming</em> by Lowell
|
||
Jay Arthur (Wiley, 1986. This is the first edition, the fourth came out in
|
||
1997).
|
||
|
||
<sect1>Copyright and Disclaimer
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
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.
|
||
|
||
|
||
<!-- ******************************************************* -->
|
||
|
||
<sect>Bash and Bash Prompts
|
||
|
||
<sect1>What is Bash?
|
||
|
||
<p>
|
||
Descended from the Bourne Shell, Bash is a GNU product, the
|
||
"<bf>B</bf>ourne <bf>A</bf>gain <bf>SH</bf>ell." 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.
|
||
|
||
<sect1>What Can Tweaking Your Bash Prompt Do For You?
|
||
|
||
<p>
|
||
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.
|
||
|
||
<sect1>Why Bother?
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
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.
|
||
|
||
|
||
<sect1>The First Step
|
||
|
||
<p>
|
||
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 <ref id="setps"
|
||
name="Setting the PS? Strings Permanently">.
|
||
|
||
<p>
|
||
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:
|
||
|
||
<tscreen><verb>
|
||
[giles@nikola giles]$ SAVE=$PS1
|
||
[giles@nikola giles]$
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
The simplest prompt would be a single character, such as:
|
||
|
||
<tscreen><verb>
|
||
[giles@nikola giles]$ PS1=$
|
||
$ls
|
||
bin mail
|
||
$
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
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
|
||
|
||
<tscreen><verb>
|
||
$PS1="$ "
|
||
$ ls
|
||
bin mail
|
||
$
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
which forces a space after the prompt, making it more readable. To restore
|
||
your original prompt, just call up the variable you stored:
|
||
|
||
<tscreen><verb>
|
||
$ PS1=$SAVE
|
||
[giles@nikola giles]$
|
||
</verb></tscreen>
|
||
|
||
<sect1>Bash Prompt Escape Sequences<label id="bpescapes">
|
||
|
||
<p>
|
||
There are a lot of escape sequences offered by the Bash shell for
|
||
insertion in the prompt. From the Bash 2.02 man page:
|
||
|
||
<tscreen><verb>
|
||
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
|
||
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
Continuing where we left off:
|
||
|
||
<tscreen><verb>
|
||
[giles@nikola giles]$ PS1="\u@\h \W> "
|
||
giles@nikola giles> ls
|
||
bin mail
|
||
giles@nikola giles>
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
This is similar to the default on most Linux distributions. I wanted a
|
||
slightly different appearance, so I changed this to:
|
||
|
||
<tscreen><verb>
|
||
giles@nikola giles> PS1="[\t][\u@\h:\w]\$ "
|
||
[21:52:01][giles@nikola:~]$ ls
|
||
bin mail
|
||
[21:52:15][giles@nikola:~]$
|
||
</verb></tscreen>
|
||
|
||
<sect1>Setting the PS? Strings Permanently<label id="setps">
|
||
|
||
<p>
|
||
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 (<htmlurl
|
||
url="mailto:johan19@idt.net" name="johan19@idt.net">) writes:
|
||
|
||
<quote>
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
therefore it should be stressed that PS1=..blah.. should be in .bashrc
|
||
and not .profile.
|
||
|
||
</quote>
|
||
|
||
<p>
|
||
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.
|
||
|
||
|
||
<!-- ****************************************************** -->
|
||
|
||
<sect>Bash Programming and Shell Scripts
|
||
|
||
<sect1>Variables
|
||
|
||
<p>
|
||
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 <em>Learning the Bash Shell</em> 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.
|
||
|
||
<p>
|
||
Variables in Bash are assigned much as they are in any programming
|
||
language:
|
||
|
||
<tscreen><verb>
|
||
testvar=5
|
||
foo=zen
|
||
bar="bash prompt"
|
||
</verb></tscreen>
|
||
|
||
Quotes are only needed in an assignment if a space (or special character,
|
||
discussed shortly) is a part of the variable.
|
||
|
||
<p>
|
||
Variables are referenced slightly differently than they are assigned:
|
||
|
||
<tscreen><verb>
|
||
> echo $testvar
|
||
5
|
||
> echo $foo
|
||
zen
|
||
> echo ${bar}
|
||
bash prompt
|
||
> echo $NotAssigned
|
||
|
||
>
|
||
</verb></tscreen>
|
||
|
||
A variable can be referred to as <bf>$bar</bf> or <bf>${bar}</bf>. The
|
||
braces are useful when it is unclear what is being referenced: if I write
|
||
<bf>$barley</bf> do I mean <bf>${bar}ley</bf> or <bf>${barley}</bf>? Note
|
||
also that referencing a value that hasn't been assigned doesn't generate an
|
||
error, instead returning nothing.
|
||
|
||
<sect1>Quotes and Special Characters
|
||
|
||
<p>
|
||
If you wish to include a special character in a variable, you will have to
|
||
quote it differently:
|
||
|
||
<tscreen><verb>
|
||
> newvar=$testvar
|
||
> echo $newvar
|
||
5
|
||
> newvar="$testvar"
|
||
> echo $newvar
|
||
5
|
||
> newvar='$testvar'
|
||
> echo $newvar
|
||
$testvar
|
||
> newvar=\$testvar
|
||
> echo $newvar
|
||
$testvar
|
||
>
|
||
</verb></tscreen>
|
||
|
||
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 <bf>eval</bf>
|
||
to dereference the stored variable name:
|
||
|
||
<tscreen><verb>
|
||
> echo $testvar
|
||
5
|
||
> echo $newvar
|
||
$testvar
|
||
> eval echo $newvar
|
||
5
|
||
>
|
||
</verb></tscreen>
|
||
|
||
Normally, the shell does only one round of substitutions on the expression
|
||
it is evaluating: if you say <bf>echo $newvar</bf> the shell will only go
|
||
so far as to determine that <bf>$newvar</bf> is equal to the text string
|
||
<bf>$testvar</bf>, it won't evaluate what <bf>$testvar</bf> is equal to.
|
||
<bf>eval</bf> forces that evaluation.
|
||
|
||
<sect1>Command Substitution
|
||
|
||
<p>
|
||
In almost all cases in this document, I use the $(<command>)
|
||
convention for command substitution: that is,
|
||
|
||
<tscreen><verb>
|
||
$(date +%H%M)
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
means "substitute the output from the <bf>date +%H%M</bf> 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 (<TT>`date +%H%M`</TT>). 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\' ).
|
||
|
||
<sect1>Non-Printing Characters in Prompts<label id="nonprintingchars">
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
If I want a very simple prompt consisting of a greater-than sign and a
|
||
space:
|
||
|
||
<tscreen><verb>
|
||
[giles@nikola giles]$ PS1='> '
|
||
>
|
||
</verb></tscreen>
|
||
|
||
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):
|
||
|
||
<tscreen><verb>
|
||
> PS1='\033[1;33m>\033[0m '
|
||
>
|
||
</verb></tscreen>
|
||
|
||
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.
|
||
|
||
<p>
|
||
So use this instead:
|
||
|
||
<tscreen><verb>
|
||
> PS1='\[\033[1;33m\]>\[\033[0m\] '
|
||
</verb></tscreen>
|
||
|
||
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
|
||
'\[' and '\]' which tells the shell "everything between these escaped
|
||
square brackets, including the brackets themselves, is a non-printing
|
||
character." The same is done with the '\033[0m' that ends the colour.
|
||
|
||
<sect1>Sourcing a File
|
||
|
||
<p>
|
||
When a file is sourced (by typing either <bf>source filename</bf> or <bf>.
|
||
filename</bf> 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.
|
||
|
||
<p>
|
||
In examples, you will find that I often include <bf>#!/bin/bash</bf> at the
|
||
beginning of files including functions. This is <bf>not</bf> necessary if
|
||
you are sourcing a file, just as it isn't necessary to <bf>chmod +x</bf> 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.
|
||
|
||
<sect1>Functions, Aliases, and the Environment
|
||
|
||
<p>
|
||
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:
|
||
|
||
<p>
|
||
"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."
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
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."
|
||
|
||
<p>
|
||
Aliases are simple to create:
|
||
|
||
<tscreen><verb>
|
||
alias d="ls --color=tty --classify"
|
||
alias v="d --format=long"
|
||
alias rm="rm -i"
|
||
</verb></tscreen>
|
||
|
||
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.)
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
To modify the behaviour of <bf>ls</bf>, you could do something like the
|
||
following:
|
||
|
||
<tscreen><verb>
|
||
function lf
|
||
{
|
||
ls --color=tty --classify $*
|
||
echo "$(ls -l $* | wc -l) files"
|
||
}
|
||
</verb></tscreen>
|
||
|
||
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.
|
||
|
||
|
||
<!-- *********************************************************** -->
|
||
|
||
<sect>External Commands
|
||
|
||
<sect1>PROMPT_COMMAND
|
||
|
||
<p>
|
||
Bash provides another environment variable called <bf>PROMPT_COMMAND</bf>.
|
||
The contents of this variable are executed as a regular Bash command
|
||
just before Bash displays a prompt.
|
||
|
||
<tscreen><verb>
|
||
[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:~]
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
What happened above was that I changed PS1 to no longer include the
|
||
<TT>\t</TT> escape sequence, so the time was no longer a part of the
|
||
prompt. Then I used <TT>date +%H%M</TT> to display the time in a format
|
||
I like better. But it appears on a different line than the prompt.
|
||
Tidying this up using <TT>echo -n ...</TT> 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.
|
||
|
||
<tscreen><verb>
|
||
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:~]
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
<TT>echo -n ...</TT> controls the output of the <TT>date</TT> command and
|
||
supresses the trailing newline, allowing the prompt to appear all on one
|
||
line. At the end, I used the <TT>unset</TT> command to remove the
|
||
PROMPT_COMMAND environment variable.
|
||
|
||
|
||
<sect1>External Commands in the Prompt
|
||
|
||
<p>
|
||
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 <bf>fast</bf> 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.)
|
||
|
||
<tscreen><verb>
|
||
[21:58:33][giles@nikola:~]$ PS1="[\$(date +%H%M)][\u@\h:\w]\$ "
|
||
[2159][giles@nikola:~]$ ls
|
||
bin mail
|
||
[2200][giles@nikola:~]$
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
Linux comes with a lot of small utility programs like <bf>date</bf>,
|
||
<bf>grep</bf>, or <bf>wc</bf> 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.
|
||
|
||
<p>
|
||
An example of a small shell script used within a prompt is given below:
|
||
|
||
<code>
|
||
#!/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"
|
||
</code>
|
||
|
||
<p>
|
||
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:
|
||
|
||
<tscreen><verb>
|
||
[2158][giles@nikola:~]$ PS1="[\u@\h:\w (\$(lsbytesum) Mb)]\$ "
|
||
[giles@nikola:~ (0 Mb)]$ cd /bin
|
||
[giles@nikola:/bin (4.498 Mb)]$
|
||
</verb></tscreen>
|
||
|
||
<sect1>What to Put in Your Prompt
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
Dan's prompt is minimal but very effective, particularly for the way he
|
||
works.
|
||
|
||
<tscreen><verb>
|
||
[giles@nikola:~]$ cur_tty=$(tty | sed -e "s/.*tty\(.*\)/\1/")
|
||
[giles@nikola:~]$ echo $cur_tty
|
||
p4
|
||
[giles@nikola:~]$ PS1="\!,$cur_tty,\$?\$ "
|
||
1095,p4,0$
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>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:
|
||
|
||
<tscreen><verb>
|
||
[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]#
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
Torben uses <bf>awk</bf> 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.
|
||
|
||
<p>
|
||
<bf>NOTE:</bf> There is a known bug in Bash 2.02 that causes the
|
||
<bf>jobs</bf> 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.
|
||
|
||
|
||
|
||
<!-- ********************************************************* -->
|
||
|
||
<sect>Xterm Title Bar Manipulations<label id="xterm-title-bar">
|
||
|
||
<p>
|
||
Non-printing escape sequences can be used to produce interesting
|
||
effects in prompts. To use these escape sequences, you need to enclose
|
||
them in <bf>\[</bf> and <bf>\]</bf> (as discussed in <ref
|
||
id="nonprintingchars" name="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 <bf>\033[</bf> in Bash prior
|
||
to version 2, or by either <bf>\033[</bf> or <bf>\e[</bf> in later versions.
|
||
|
||
<p>
|
||
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.
|
||
|
||
<code>
|
||
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='+ '
|
||
}
|
||
</code>
|
||
|
||
<p>
|
||
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
|
||
<TT>unset proml</TT>. 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.
|
||
|
||
<p>
|
||
I define this as a function because this is how the Bashprompt package
|
||
(discussed later in this document: <ref id="bppackage" name="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:
|
||
|
||
<tscreen><verb>
|
||
[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
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
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
|
||
<bf>\u@\h:\w</bf>, 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.
|
||
|
||
<p>
|
||
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.
|
||
|
||
|
||
<!-- ******************************************************* -->
|
||
|
||
<sect>ANSI Escape Sequences: Colours and Cursor Movement
|
||
|
||
<sect1>Colours
|
||
|
||
<p>
|
||
As mentioned before, non-printing escape sequences have to be enclosed in
|
||
<bf>\[\033[</bf> and <bf>\]</bf>. For colour escape sequences, they should
|
||
also be followed by a lowercase <bf>m</bf>.
|
||
|
||
<p>
|
||
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.
|
||
|
||
<p>
|
||
To include blue text in the prompt:
|
||
|
||
<tscreen><verb>
|
||
PS1="\[\033[34m\][\$(date +%H%M)][\u@\h:\w]$ "
|
||
</verb></tscreen>
|
||
|
||
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 <bf>bold</bf> code
|
||
might help:
|
||
|
||
<tscreen><verb>
|
||
PS1="\[\033[1;34m\][\$(date +%H%M)][\u@\h:\w]$\[\033[0m\] "
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
The prompt is now in light blue, and it ends by switching the colour
|
||
back to nothing (whatever foreground colour you had previously).
|
||
|
||
<p>
|
||
Here are the rest of the colour equivalences:
|
||
|
||
<tscreen><verb>
|
||
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
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
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 <bf>1;31</bf> isn't "Light Red," but "Bold Red." This is true of
|
||
all the colours.
|
||
|
||
<p>
|
||
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:
|
||
<bf>\[\033[44;1;31m\]</bf>, although setting the colours separately seems
|
||
to work better (ie. <bf>\[\033[44m\]\[\033[1;31m\]</bf>). Other codes
|
||
available include 4: Underscore, 5: Blink, 7: Inverse, and 8: Concealed.
|
||
|
||
<p>
|
||
<bf>Aside:</bf> 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.
|
||
|
||
<p>
|
||
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:
|
||
|
||
<code>
|
||
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 "
|
||
}
|
||
</code>
|
||
|
||
<p>
|
||
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:
|
||
|
||
<tscreen><verb>
|
||
--(giles@nikola)-(75/ttyp7)-(1908/12-Oct-98)--
|
||
--($:~/tmp)--
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
To help myself remember what colours are available, I wrote the following
|
||
script which echoes all the colours to screen:
|
||
|
||
<code>
|
||
#!/bin/bash
|
||
#
|
||
# This file echoes a bunch of colour codes to the terminal to demonstrate
|
||
# what's available. Each line is one colour on black and gray
|
||
# backgrounds, with the code in the middle. Verified to work on white,
|
||
# black, and green BGs (2 Dec 98).
|
||
#
|
||
echo " On Light Gray: On Black:"
|
||
echo -e "\033[47m\033[1;37m White \033[0m\
|
||
1;37m \
|
||
\033[40m\033[1;37m White \033[0m"
|
||
echo -e "\033[47m\033[37m Light Gray \033[0m\
|
||
37m \
|
||
\033[40m\033[37m Light Gray \033[0m"
|
||
echo -e "\033[47m\033[1;30m Gray \033[0m\
|
||
1;30m \
|
||
\033[40m\033[1;30m Gray \033[0m"
|
||
echo -e "\033[47m\033[30m Black \033[0m\
|
||
30m \
|
||
\033[40m\033[30m Black \033[0m"
|
||
echo -e "\033[47m\033[31m Red \033[0m\
|
||
31m \
|
||
\033[40m\033[31m Red \033[0m"
|
||
echo -e "\033[47m\033[1;31m Light Red \033[0m\
|
||
1;31m \
|
||
\033[40m\033[1;31m Light Red \033[0m"
|
||
echo -e "\033[47m\033[32m Green \033[0m\
|
||
32m \
|
||
\033[40m\033[32m Green \033[0m"
|
||
echo -e "\033[47m\033[1;32m Light Green \033[0m\
|
||
1;32m \
|
||
\033[40m\033[1;32m Light Green \033[0m"
|
||
echo -e "\033[47m\033[33m Brown \033[0m\
|
||
33m \
|
||
\033[40m\033[33m Brown \033[0m"
|
||
echo -e "\033[47m\033[1;33m Yellow \033[0m\
|
||
1;33m \
|
||
\033[40m\033[1;33m Yellow \033[0m"
|
||
echo -e "\033[47m\033[34m Blue \033[0m\
|
||
34m \
|
||
\033[40m\033[34m Blue \033[0m"
|
||
echo -e "\033[47m\033[1;34m Light Blue \033[0m\
|
||
1;34m \
|
||
\033[40m\033[1;34m Light Blue \033[0m"
|
||
echo -e "\033[47m\033[35m Purple \033[0m\
|
||
35m \
|
||
\033[40m\033[35m Purple \033[0m"
|
||
echo -e "\033[47m\033[1;35m Pink \033[0m\
|
||
1;35m \
|
||
\033[40m\033[1;35m Pink \033[0m"
|
||
echo -e "\033[47m\033[36m Cyan \033[0m\
|
||
36m \
|
||
\033[40m\033[36m Cyan \033[0m"
|
||
echo -e "\033[47m\033[1;36m Light Cyan \033[0m\
|
||
1;36m \
|
||
\033[40m\033[1;36m Light Cyan \033[0m"
|
||
|
||
</code>
|
||
|
||
<sect1>Cursor Movement
|
||
|
||
<p>
|
||
ANSI escape sequences allow you to move the cursor around the screen at
|
||
will. This is more useful for full screen user interfaces generated by
|
||
shell scripts, but can also be used in prompts. The movement escape
|
||
sequences are as follows:
|
||
|
||
<tscreen><verb>
|
||
- Position the Cursor:
|
||
\033[<L>;<C>H
|
||
Or
|
||
\033[<L>;<C>f
|
||
puts the cursor at line L and column C.
|
||
- Move the cursor up N lines:
|
||
\033[<N>A
|
||
- Move the cursor down N lines:
|
||
\033[<N>B
|
||
- Move the cursor forward N columns:
|
||
\033[<N>C
|
||
- Move the cursor backward N columns:
|
||
\033[<N>D
|
||
|
||
- Clear the screen, move to (0,0):
|
||
\033[2J
|
||
- Erase to end of line:
|
||
\033[K
|
||
|
||
- Save cursor position:
|
||
\033[s
|
||
- Restore cursor position:
|
||
\033[u
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
The latter two codes are NOT honoured by many terminal emulators. The only
|
||
ones that I'm aware of that do are xterm and nxterm - even though the
|
||
majority of terminal emulators are based on xterm code. As far as I can
|
||
tell, rxvt, kvt, xiterm, and Eterm do not support them. They are supported
|
||
on the console.
|
||
|
||
<p>
|
||
Try putting in the following line of code at the prompt (it's a little
|
||
clearer what it does if the prompt is several lines down the terminal when
|
||
you put this in): <tt>echo -en "\033[7A\033[1;35m BASH \033[7B\033[6D"</tt>
|
||
This should move the cursor seven lines up screen, print the word " BASH ",
|
||
and then return to where it started to produce a normal prompt. This isn't
|
||
a prompt: it's just a demonstration of moving the cursor on screen, using
|
||
colour to emphasize what has been done.
|
||
|
||
<p>
|
||
Save this in a file called "clock":
|
||
|
||
<code>
|
||
#!/bin/bash
|
||
|
||
function prompt_command {
|
||
let prompt_x=$COLUMNS-5
|
||
}
|
||
|
||
PROMPT_COMMAND=prompt_command
|
||
|
||
function clock {
|
||
local BLUE="\[\033[0;34m\]"
|
||
local RED="\[\033[0;31m\]"
|
||
local LIGHT_RED="\[\033[1;31m\]"
|
||
local WHITE="\[\033[1;37m\]"
|
||
local NO_COLOUR="\[\033[0m\]"
|
||
case $TERM in
|
||
xterm*)
|
||
TITLEBAR='\[\033]0;\u@\h:\w\007\]'
|
||
;;
|
||
*)
|
||
TITLEBAR=""
|
||
;;
|
||
esac
|
||
|
||
PS1="${TITLEBAR}\
|
||
\[\033[s\033[1;\$(echo -n \${prompt_x})H\]\
|
||
$BLUE[$LIGHT_RED\$(date +%H%M)$BLUE]\[\033[u\033[1A\]
|
||
$BLUE[$LIGHT_RED\u@\h:\w$BLUE]\
|
||
$WHITE\$$NO_COLOUR "
|
||
PS2='> '
|
||
PS4='+ '
|
||
}
|
||
</code>
|
||
|
||
<p>
|
||
This prompt is fairly plain, except that it keeps a 24 hour clock in the
|
||
upper right corner of the terminal (even if the terminal is resized). This
|
||
will NOT work on the terminal emulators that I mentioned that don't accept
|
||
the save and restore cursor position codes. If you try to run this prompt
|
||
in any of those terminal emulators, the clock will appear correctly, but
|
||
the prompt will be trapped on the second line of the terminal.
|
||
|
||
<p>See also <ref id="clock3" name="The Elegant Useless Clock Prompt"> for a
|
||
more extensive use of these codes.
|
||
|
||
<sect1>Moving the Cursor With tput
|
||
|
||
<p>
|
||
As with so many things in Unix, there is more than one way to achieve the
|
||
same ends. A utility called "tput" can also be used to move the cursor
|
||
around the screen, or get back information about the status of the
|
||
terminal. "tput" for cursor positioning is less flexible than ANSI escape
|
||
sequences: you can only move the cursor to an absolute position, you can't
|
||
move it relative to its current position. I don't use "tput," so I'm not
|
||
going to explain it in detail. Type "man tput" and you'll know as much as
|
||
I do.
|
||
|
||
|
||
<!-- ******************************************************** -->
|
||
|
||
<sect>Special Characters: Octal Escape Sequences
|
||
|
||
<p>
|
||
Outside of the characters that you can type on your keyboard, there are a
|
||
lot of other characters you can print on your screen. I've created a
|
||
script to allow you to check out what the font you're using has available
|
||
for you. The main command you need to use to utilise these characters is
|
||
"echo -e". The "-e" switch tells echo to enable interpretation of
|
||
backslash-escaped characters. What you see when you look at octal 200-400
|
||
will be very different with a VGA font from what you will see with a
|
||
standard Linux font. Be warned that some of these escape sequences have
|
||
odd effects on your terminal, and I haven't tried to prevent them from
|
||
doing whatever they do. The linedraw and block characters (which many of
|
||
us became familiar with with Word Perfect) that are used heavily by the
|
||
Bashprompt project are between octal 260 and 337.
|
||
|
||
<code>
|
||
#!/bin/bash
|
||
|
||
# Script: escgen
|
||
|
||
function usage {
|
||
echo -e "\033[1;34mescgen\033[0m <lower_octal_value> [<higher_octal_value>]"
|
||
echo " Octal escape sequence generator: print all octal escape sequences"
|
||
echo " between the lower value and the upper value. If a second value"
|
||
echo " isn't supplied, print eight characters."
|
||
echo " 1998 - Giles Orr, no warranty."
|
||
exit 1
|
||
}
|
||
|
||
if [ "$#" -eq "0" ]
|
||
then
|
||
echo -e "\033[1;31mPlease supply one or two values.\033[0m"
|
||
usage
|
||
fi
|
||
let lower_val=${1}
|
||
if [ "$#" -eq "1" ]
|
||
then
|
||
# If they don't supply a closing value, give them eight characters.
|
||
upper_val=$(echo -e "obase=8 \n ibase=8 \n $lower_val+10 \n quit" | bc)
|
||
else
|
||
let upper_val=${2}
|
||
fi
|
||
if [ "$#" -gt "2" ]
|
||
then
|
||
echo -e "\033[1;31mPlease supply two values.\033[0m"
|
||
echo
|
||
usage
|
||
fi
|
||
if [ "${lower_val}" -gt "${upper_val}" ]
|
||
then
|
||
echo -e "\033[1;31m${lower_val} is larger than ${upper_val}."
|
||
echo
|
||
usage
|
||
fi
|
||
if [ "${upper_val}" -gt "777" ]
|
||
then
|
||
echo -e "\033[1;31mValues cannot exceed 777.\033[0m"
|
||
echo
|
||
usage
|
||
fi
|
||
|
||
let i=$lower_val
|
||
let line_count=1
|
||
let limit=$upper_val
|
||
while [ "$i" -lt "$limit" ]
|
||
do
|
||
octal_escape="\\$i"
|
||
echo -en "$i:'$octal_escape' "
|
||
if [ "$line_count" -gt "7" ]
|
||
then
|
||
echo
|
||
# Put a hard return in.
|
||
let line_count=0
|
||
fi
|
||
let i=$(echo -e "obase=8 \n ibase=8 \n $i+1 \n quit" | bc)
|
||
let line_count=$line_count+1
|
||
done
|
||
echo
|
||
|
||
</code>
|
||
|
||
<p>
|
||
You can also use <bf>xfd</bf> to display all the characters in an X font,
|
||
with the command "xfd -fn <fontname>". Clicking on any given
|
||
character will give you lots of information about that character, including
|
||
its octal value. The script given above will be useful on the console, and
|
||
if you aren't sure of the current font name.
|
||
|
||
|
||
<!-- ******************************************************** -->
|
||
|
||
<sect>The Bash Prompt Package<label id="bppackage">
|
||
|
||
<sect1>Availability
|
||
|
||
<p>
|
||
The Bash Prompt package is available at <htmlurl
|
||
url="http://bash.current.nu" name="http://bash.current.nu">, and is the
|
||
work of several people, co-ordinated by Rob Current (aka BadLandZ). The
|
||
package is an early beta, but offers a simple way of using multiple prompts
|
||
(or themes), allowing you to set prompts for login shells, and for
|
||
subshells (ie. putting PS1 strings in ˜/.bash_profile and
|
||
˜/.bashrc). Most of the themes use the extended VGA character set,
|
||
so they look bad unless they're used with VGA fonts (which aren't the
|
||
default on most systems).
|
||
|
||
<sect1>Xterm Fonts
|
||
|
||
<p>
|
||
To use some of the most attractive prompts in the Bash Prompt package, you
|
||
need to get and install fonts that support the character sets expected by
|
||
the prompts. These are "VGA Fonts," which support different character sets
|
||
than regular Xterm fonts. Standard Xterm fonts support an extended
|
||
alphabet, including a lot of letters with accents. In VGA fonts, this
|
||
material is replaced by graphical characters - blocks, dots, lines. I
|
||
asked for an explanation of this difference, and S<>rgio Vale e Pace
|
||
(space@gold.com.br) wrote me:
|
||
|
||
<quote>
|
||
<p>
|
||
I love computer history so here goes:
|
||
|
||
<p>
|
||
When IBM designed the first PC they needed some character codes to use, so
|
||
they got the ASCII character table (128 numbers, letters, and some
|
||
punctuation) and to fill a byte addressed table they added 128 more
|
||
characters. Since the PC was designed to be a home computer, they fill the
|
||
remaining 128 characters with dots, lines, points, etc, to be able to do
|
||
borders, and grayscale effects (remember that we are talking about 2 color
|
||
graphics).
|
||
|
||
<p>
|
||
Time passes, PCs become a standard, IBM creates more powerful systems and
|
||
the VGA standard is born, along with 256 colour graphics, and IBM continues
|
||
to include their IBM-ASCII characters table.
|
||
|
||
<p>
|
||
More time passes, IBM has lost their leadership in the PC market, and the
|
||
OS authors dicover that there are other languages in the world that use
|
||
non-english characters, so they add international alphabet support in their
|
||
systems. Since we now have bright and colorful screens, we can trash the
|
||
dots, lines, etc. and use their space for accented characters and some
|
||
greek letters, which you'll see in Linux.
|
||
|
||
</quote>
|
||
|
||
<sect1>Changing the Xterm Font
|
||
|
||
<p>
|
||
Getting and installing these fonts is a somewhat involved process. First,
|
||
retrieve the font(s). Next, ensure they're .pcf or .pcf.gz files. If
|
||
they're .bdf files, investigate the "bdftopcf" command (ie. read the man
|
||
page). Drop the .pcf or .pcf.gz files into the
|
||
/usr/X11R6/lib/X11/fonts/misc dir (this is the correct directory for RedHat
|
||
5.1 and Slackware 3.4, it may be different on other distributions). "cd"
|
||
to that directory, and run the "mkfontdir" command. Then run "xset fp
|
||
rehash". Sometimes it's a good idea to go into the fonts.alias file in the
|
||
same directory, and create shorter alias names for the fonts.
|
||
|
||
<p>
|
||
To use the new fonts, you start your Xterm program of choice with the
|
||
appropriate command to your Xterm, which can be found either in the man
|
||
page or by using the "--help" parameter on the command line. Popular terms
|
||
would be used as follows:
|
||
|
||
<tscreen><verb>
|
||
xterm -font <fontname>
|
||
</verb></tscreen>
|
||
<bf>OR</bf>
|
||
<tscreen><verb>
|
||
xterm -fn <fontname> -fb <fontname-bold>
|
||
Eterm -F <fontname>
|
||
rxvt -fn <fontname>
|
||
</verb></tscreen>
|
||
|
||
<p>
|
||
VGA fonts are available from <em>Stumpy's ANSI Fonts</em> page at <htmlurl
|
||
url="http://home.earthlink.net/~us5zahns/enl/ansifont.html"
|
||
name="http://home.earthlink.net/~us5zahns/enl/ansifont.html"> (which I have
|
||
borrowed from extensively while writing this).
|
||
|
||
|
||
<!-- *************************************************** -->
|
||
|
||
<sect>Loading a Different Prompt
|
||
|
||
<sect1>Loading a Different Prompt, Later
|
||
<p>
|
||
The explanations in this HOWTO have shown how to make PS1 environment
|
||
variables, or how to incorporate those PS1 and PS2 strings into functions
|
||
that could be called by ˜/.bashrc or as a theme by the bashprompt
|
||
package.
|
||
|
||
<p>
|
||
Using the bashprompt package, you would type <TT>bashprompt -i</TT> to see
|
||
a list of available themes. To set the prompt in future login shells
|
||
(primarily the console, but also telnet and Xterms, depending on how your
|
||
Xterms are set up), you would type <TT>bashprompt -l themename</TT>.
|
||
bashprompt then modifies your ˜/.bash_profile to call the requested
|
||
theme when it starts. To set the prompt in future subshells (usually
|
||
Xterms, rxvt, etc.), you type <TT>bashprompt -s themename</TT>, and
|
||
bashprompt modifies your ˜/.bashrc file to call the appropriate theme
|
||
at startup.
|
||
|
||
<p>
|
||
See also <ref id="setps" name="Setting the PS? Strings Permanently"> for
|
||
Johan Kullstam's note regarding the importance of putting the PS?
|
||
strings in ˜/.bashrc .
|
||
|
||
<sect1>Loading a Different Prompt, Immediately
|
||
|
||
<p>
|
||
You can change the prompt in your current terminal (using the example
|
||
"elite" function above) by typing "<TT>source elite</TT>" followed by
|
||
"<TT>elite</TT>" (assuming that the elite function file is the working
|
||
directory). This is somewhat cumbersome, and leaves you with an extra
|
||
function (elite) in your environment space - if you want to clean up the
|
||
environment, you would have to type "<TT>unset elite</TT>" as well. This
|
||
would seem like an ideal candidate for a small shell script, but a script
|
||
doesn't work here because the script cannot change the environment of your
|
||
current shell: it can only change the environment of the subshell it runs
|
||
in. As soon as the script stops, the subshell goes away, and the changes
|
||
the script made to the environment are gone. What <bf>can</bf> change
|
||
environment variables of your current shell are environment functions. The
|
||
bashprompt package puts a function called "callbashprompt" into your
|
||
environment, and, while they don't document it, it can be called to load
|
||
any bashprompt theme on the fly. It looks in the theme directory it
|
||
installed (the theme you're calling has to be there), sources the function
|
||
you asked for, loads the function, and then unsets the function, thus
|
||
keeping your environment uncluttered. "callbashprompt" wasn't intended to
|
||
be used this way, and has no error checking, but if you keep that in mind,
|
||
it works quite well.
|
||
|
||
|
||
<!-- ***************************************************** -->
|
||
|
||
<sect>Loading Prompt Colours Dynamically
|
||
|
||
<sect1>A "Proof of Concept" Example
|
||
|
||
<p>
|
||
This is a "proof of concept" more than an attractive prompt: changing
|
||
colours within the prompt dynamically. In this example, the colour of the
|
||
host name changes depending on the load (as a warning).
|
||
|
||
<code>
|
||
#!/bin/bash
|
||
# "hostloadcolour" - 17 October 98, by Giles
|
||
#
|
||
# The idea here is to change the colour of the host name in the prompt,
|
||
# depending on a threshold load value.
|
||
|
||
# THRESHOLD_LOAD is the value of the one minute load (multiplied
|
||
# by one hundred) at which you want
|
||
# the prompt to change from COLOUR_LOW to COLOUR_HIGH
|
||
THRESHOLD_LOAD=200
|
||
COLOUR_LOW='1;34'
|
||
# light blue
|
||
COLOUR_HIGH='1;31'
|
||
# light red
|
||
|
||
function prompt_command {
|
||
ONE=$(uptime | sed -e "s/.*load average: \(.*\...\), \(.*\...\), \(.*\...\)/\1/" -e "s/ //g")
|
||
# Apparently, "scale" in bc doesn't apply to multiplication, but does
|
||
# apply to division.
|
||
ONEHUNDRED=$(echo -e "scale=0 \n $ONE/0.01 \nquit \n" | bc)
|
||
if [ $ONEHUNDRED -gt $THRESHOLD_LOAD ]
|
||
then
|
||
HOST_COLOUR=$COLOUR_HIGH
|
||
# Light Red
|
||
else
|
||
HOST_COLOUR=$COLOUR_LOW
|
||
# Light Blue
|
||
fi
|
||
}
|
||
|
||
function hostloadcolour {
|
||
|
||
PROMPT_COMMAND=prompt_command
|
||
PS1="[$(date +%H%M)][\u@\[\033[\$(echo -n \$HOST_COLOUR)m\]\h\[\033[0m\]:\w]$ "
|
||
}
|
||
</code>
|
||
|
||
<p>
|
||
Using your favorite editor, save this to a file named "hostloadcolour". If
|
||
you have the Bashprompt package installed, this will work as a theme. If you
|
||
don't, type <TT>source hostloadcolour</TT> and then <TT>hostloadcolour</TT>.
|
||
Either way, "prompt_command" becomes a function in your environment.
|
||
If you examine the code, you will notice that the colours ($COLOUR_HIGH and
|
||
$COLOUR_LOW) are set using only a partial colour code, ie. "1;34" instead of
|
||
"\[\033[1;34m\]", which I would have preferred. I have been unable to get
|
||
it to work with the complete code. Please let me know if you manage this.
|
||
|
||
|
||
<!-- ******************************************************** -->
|
||
|
||
<sect>Prompt Code Snippets
|
||
|
||
<p>
|
||
This section shows how to put various pieces of information into the Bash
|
||
prompt. There are an infinite number of things that could be put in your
|
||
prompt. Feel free to send me examples, I will try to include what I think
|
||
will be most widely used. If you have an alternate way to retrieve a piece
|
||
of information here, and feel your method is more efficient, please contact
|
||
me. It's easy to write bad code, I do it often, but it's great to write
|
||
elegant code, and a pleasure to read it. I manage it every once in a
|
||
while, and would love to have more of it to put in here.
|
||
|
||
<p>
|
||
To incorporate shell code in prompts, it has to be escaped. Usually, this
|
||
will mean putting it inside <tt>\$(<command>)</tt> so that the output
|
||
of <tt>command</tt> is substituted each time the prompt is generated.
|
||
|
||
<sect1>Built-in Escape Sequences
|
||
|
||
<p>
|
||
See <ref id="bpescapes" name="Bash Prompt Escape Sequences"> for a complete
|
||
list of built-in escape sequences. This list is taken directly from the
|
||
Bash man page, so you can also look there.
|
||
|
||
<sect1>Date and Time
|
||
|
||
<p>
|
||
If you don't like the built-ins for date and time, extracting the same
|
||
information from the <tt>date</tt> command is relatively easy. Examples
|
||
already seen in this HOWTO include <tt>date +%H%M</tt>, which will put
|
||
in the hour in 24 hour format, and the minute. <tt>date "+%A, %d %B
|
||
%Y"</tt> will give something like "Sunday, 06 June 1999". For a full list
|
||
of the interpreted sequences, type <tt>date --help</tt> or <tt>man
|
||
date</tt>.
|
||
|
||
<sect1>Counting Files in the Current Directory
|
||
|
||
<p>
|
||
To determine how many files there are in the current directory, put in
|
||
<tt>ls -l | wc -l</tt>. This uses <tt>wc</tt> wordcount to do a count of
|
||
the number of lines (-l) in the output of <tt>ls -l</tt>. It doesn't count
|
||
dotfiles. If you want to count only files and NOT include symbolic links
|
||
(just an example of what else you could do), you could use <tt>ls -l | grep
|
||
-v ^l | wc -l</tt>. Here, <tt>grep</tt> checks for any line beginning with
|
||
"l" (indicating a link), and discards that line (-v).
|
||
|
||
<sect1>Total Bytes in the Current Directory
|
||
|
||
<p>
|
||
If you want to know how much space the contents of the current directory
|
||
take up, you can use something like the following:
|
||
|
||
<code>
|
||
# The sed command replaces all the spaces with only one space.
|
||
# cut -d" " -f5 : -d determines a delimiter, which means that (in
|
||
# this case) a space begins a new column.
|
||
# -f says to take out a certain column, in this case the fifth one
|
||
|
||
let TotalBytes=0
|
||
|
||
for Bytes in $(ls -l | grep "^-" | sed -e "s/ \+/ /g" | cut -d" " -f5)
|
||
do
|
||
let TotalBytes=$TotalBytes+$Bytes
|
||
done
|
||
|
||
# The if...fi's give a more specific output in byte, kilobyte, megabyte,
|
||
# and gigabyte
|
||
|
||
if [ $TotalBytes -lt 1024 ]; then
|
||
TotalSize=$(echo -e "scale=3 \n$TotalBytes \nquit" | bc)
|
||
else if [ $TotalBytes -lt 1048576 ]; then
|
||
TotalSize=$(echo -e "scale=3 \n$TotalBytes/1024 \nquit" | bc)
|
||
else if [ $TotalBytes -lt 1073741824 ]; then
|
||
TotalSize=$(echo -e "scale=3 \n$TotalBytes/1048576 \nquit" | bc)
|
||
else
|
||
TotalSize=$(echo -e "scale=3 \n$TotalBytes/1073741824 \nquit" | bc)
|
||
fi
|
||
fi
|
||
fi
|
||
</code>
|
||
|
||
Code courtesy of Sam Schmit (id@pt.lu) and his uncle Jean-Paul, who ironed
|
||
out a fairly major bug in my original code, and just generally cleaned it
|
||
up.
|
||
|
||
<sect1>Checking the Current TTY
|
||
|
||
<p>
|
||
The <tt>tty</tt> command returns the filename of the terminal connected to
|
||
standard input. This comes in two formats on the Linux systems I have
|
||
used, either "/dev/tty4" or "/dev/pts/2". I have taken to using a more
|
||
general solution to this: <tt>tty | sed -e "s:/dev/::"</tt>, which removes
|
||
the leading "/dev/". Older systems
|
||
(in my experience, RedHat through 5.2) returned only filenames in the
|
||
"/dev/tty4" format, so I used <tt>tty | sed -e "s/.*tty\(.*\)/\1/"</tt>.
|
||
|
||
<p>
|
||
An alternative method: <tt>ps aux | grep $$ | awk '{ print $7 }'</tt>.
|
||
|
||
<sect1>Suspended Job Count
|
||
|
||
<p>
|
||
To find out how many suspended jobs you have, use <tt>jobs | wc -l | awk
|
||
'{print $1}'</tt>. <tt>awk</tt> is used to trim the output, which would
|
||
otherwise include blank spaces that waste space in a prompt. If you start
|
||
netscape from an xterm, this will also be counted. If you want to avoid
|
||
that, and only count stopped jobs, use <tt>jobs -s</tt> instead. Type
|
||
<tt>help jobs</tt> for more info on jobs. <tt>jobs</tt> will always return
|
||
nothing to a pipe in version 2.02 of Bash: this problem is not present in
|
||
any other version.
|
||
|
||
<sect1>Uptime and Load
|
||
|
||
<p>
|
||
Current load is taken from the <tt>uptime</tt> command. What I use at the
|
||
moment is <tt>uptime | sed -e "s/.*load average: \(.*\...\), .*\...,
|
||
.*\.../\1/" -e "s/ //g"</tt> which is clunky in the extreme, but works.
|
||
Replacements welcome. <tt>uptime</tt> can also be used in a very similar
|
||
manner to find out how long the machine has been up (obviously) or how many
|
||
users are logged in, and the data could be massaged with <tt>sed</tt> to
|
||
look the way you want it to.
|
||
|
||
<sect1>Number of Processes
|
||
|
||
<p>
|
||
<tt>ps ax | wc -l | tr -d " "</tt> <em>OR</em> <tt>ps ax | wc -l | awk
|
||
'{print $1}'</tt> <em>OR</em> <tt>ps ax | wc -l | sed -e "s: ::g"</tt>. In
|
||
each case, <tt>tr</tt> or <tt>awk</tt> or <tt>sed</tt> is used to remove
|
||
the undesirable whitespace.
|
||
|
||
<sect1>Controlling the Width of $PWD
|
||
|
||
<p>
|
||
Unix allows long file names, which can lead to the value of $PWD being very
|
||
long. Some people (notably the default RedHat prompt) choose to use the
|
||
basename of the current working directory (ie. "giles" if
|
||
$PWD="/home/giles"). I like more info than that, but it's often desirable
|
||
to limit the length of the directory name, and it makes the most sense to
|
||
truncate on the left.
|
||
|
||
<code>
|
||
# How many characters of the $PWD should be kept
|
||
local pwd_length=30
|
||
if [ $(echo -n $PWD | wc -c | tr -d " ") -gt $pwd_length ]
|
||
then
|
||
newPWD="...$(echo -n $PWD | sed -e "s/.*\(.\{$pwd_length\}\)/\1/")"
|
||
else
|
||
newPWD="$(echo -n $PWD)"
|
||
fi
|
||
</code>
|
||
|
||
<p>
|
||
The above code can be executed as part of PROMPT_COMMAND, and the
|
||
environment variable generated (<em>newPWD</em>) can then be included in
|
||
the prompt.
|
||
|
||
<sect1>Laptop Power
|
||
|
||
<p>
|
||
Again, this isn't elegant, but it works (most of the time). If you have a
|
||
laptop with APM installed, try <tt>power=$(apm | sed -e "s/.*:
|
||
\([1-9][0-9]*\)%/\1/" | tr -d " ")</tt> executed from PROMPT_COMMAND to
|
||
create an environment variable you can add to your prompt. This will
|
||
indicate percentage power remaining.
|
||
|
||
<sect1>Having the Prompt Ignored on Cut and Paste
|
||
|
||
<p>
|
||
|
||
This one is weird but cool. Rory Toma (rory@corp.webtv.net) wrote to
|
||
suggest a prompt like this: <tt>: rory@demon ;</tt> . How is this useful?
|
||
Well, if you type a command after the prompt (odd idea, that), you can
|
||
triple click on that line (in Linux, anyway) to highlight the whole line,
|
||
then paste that line in front of another prompt, and the stuff between the
|
||
":" and the """ is ignored, like so:
|
||
|
||
<code>
|
||
: rory@demon ; uptime
|
||
5:15pm up 6 days, 23:04, 2 users, load average: 0.00, 0.00, 0.00
|
||
: rory@demon ; : rory@demon ; uptime
|
||
5:15pm up 6 days, 23:04, 2 users, load average: 0.00, 0.00, 0.00
|
||
</code>
|
||
|
||
The prompt is a no-op, and if your PS2 is set to a space, multiple lines
|
||
can be cut and pasted as well.
|
||
|
||
<sect1>Setting the Window Title and Icon Title Separately<label
|
||
id="title-icon-bar">
|
||
|
||
<p>
|
||
A suggestion from Charles Lepple (clepple@negativezero.org) on setting the
|
||
window title of the Xterm and the title of the corresponding icon
|
||
separately (first check out the earlier section <ref id="xterm-title-bar"
|
||
name="Xterm Title Bar Manipulations">). He uses this under WindowMaker
|
||
because the title that's appropriate for an Xterm is usually too long for a
|
||
64x64 icon. "\[\e]1;icon-title\007\e]2;main-title\007\]". He says to set
|
||
this in the prompt command because "I tried putting the string in PS1, but
|
||
it causes flickering under some window managers because it results in
|
||
setting the prompt multiple times when you are editing a multi-line command
|
||
(at least under bash 1.4.x -- and I was too lazy to fully explore the
|
||
reasons behind it)." I had no trouble with it in the PS1 string, but
|
||
didn't use any multi-line commands. He also points out that it works under
|
||
xterm, xwsh, and dtterm, but not gnome-terminal (which uses only the main
|
||
title). I also found it to work with rxvt, but not kterm.
|
||
|
||
|
||
<!--
|
||
**********************************
|
||
* *
|
||
* Examples Start Here *
|
||
* *
|
||
**********************************
|
||
-->
|
||
|
||
<sect>Example Prompts
|
||
|
||
<sect1>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
|
||
<htmlurl url="http://www.interlog.com/~giles/bashprompt/prompts/"
|
||
name="http://www.interlog.com/~giles/bashprompt/prompts">. Web pages also
|
||
allow me to include pictures, which I can't include in a standard HOWTO.
|
||
All of the examples given here except Bradley Alexander's "Prompts
|
||
Depending on Connection Types" can also be seen on the web.
|
||
|
||
|
||
<sect1>A "Lightweight" Prompt
|
||
|
||
<p>
|
||
<code>
|
||
|
||
function proml {
|
||
local BLUE="\[\033[0;34m\]"
|
||
local RED="\[\033[0;31m\]"
|
||
local LIGHT_RED="\[\033[1;31m\]"
|
||
local WHITE="\[\033[1;37m\]"
|
||
local NO_COLOUR="\[\033[0m\]"
|
||
case $TERM in
|
||
xterm*)
|
||
TITLEBAR='\[\033]0;\u@\h:\w\007\]'
|
||
;;
|
||
*)
|
||
TITLEBAR=""
|
||
;;
|
||
esac
|
||
|
||
PS1="${TITLEBAR}\
|
||
$BLUE[$RED\$(date +%H%M)$BLUE]\
|
||
$BLUE[$LIGHT_RED\u@\h:\w$BLUE]\
|
||
$WHITE\$$NO_COLOUR "
|
||
PS2='> '
|
||
PS4='+ '
|
||
}
|
||
|
||
</code>
|
||
|
||
<sect1>Elite from Bashprompt Themes
|
||
|
||
<p>
|
||
Note that this requires a VGA font.
|
||
|
||
<code>
|
||
|
||
# Created by KrON from windowmaker on IRC
|
||
# Changed by Spidey 08/06
|
||
function elite {
|
||
PS1="\[\033[31m\]\332\304\[\033[34m\](\[\033[31m\]\u\[\033[34m\]@\[\033[31m\]\h\
|
||
\[\033[34m\])\[\033[31m\]-\[\033[34m\](\[\033[31m\]\$(date +%I:%M%P)\
|
||
\[\033[34m\]-:-\[\033[31m\]\$(date +%m)\[\033[34m\033[31m\]/\$(date +%d)\
|
||
\[\033[34m\])\[\033[31m\]\304-\[\033[34m]\\371\[\033[31m\]-\371\371\
|
||
\[\033[34m\]\372\n\[\033[31m\]\300\304\[\033[34m\](\[\033[31m\]\W\[\033[34m\])\
|
||
\[\033[31m\]\304\371\[\033[34m\]\372\[\033[00m\]"
|
||
PS2="> "
|
||
}
|
||
|
||
</code>
|
||
|
||
<sect1>A "Power User" Prompt
|
||
|
||
<p>
|
||
I actually do use this prompt, but it results in noticeable delays in the
|
||
appearance of the prompt on a single-user PII-400, so I wouldn't recommend
|
||
using it on a multi-user P-100 or anything ... Look at it for ideas,
|
||
rather than as a practical prompt.
|
||
|
||
<p>
|
||
|
||
<code>
|
||
|
||
#!/bin/bash
|
||
#----------------------------------------------------------------------
|
||
# POWER USER PROMPT "pprom2"
|
||
#----------------------------------------------------------------------
|
||
#
|
||
# Created August 98, Last Modified 9 November 98 by Giles
|
||
#
|
||
# Problem: when load is going down, it says "1.35down-.08", get rid
|
||
# of the negative
|
||
|
||
function prompt_command
|
||
{
|
||
# Create TotalMeg variable: sum of visible file sizes in current directory
|
||
local TotalBytes=0
|
||
for Bytes in $(ls -l | grep "^-" | cut -c30-41)
|
||
do
|
||
let TotalBytes=$TotalBytes+$Bytes
|
||
done
|
||
TotalMeg=$(echo -e "scale=3 \nx=$TotalBytes/1048576\n if (x<1) {print \"0\"} \n print x \nquit" | bc)
|
||
|
||
# This is used to calculate the differential in load values
|
||
# provided by the "uptime" command. "uptime" gives load
|
||
# averages at 1, 5, and 15 minute marks.
|
||
#
|
||
local one=$(uptime | sed -e "s/.*load average: \(.*\...\), \(.*\...\), \(.*\...\)/\1/" -e "s/ //g")
|
||
local five=$(uptime | sed -e "s/.*load average: \(.*\...\), \(.*\...\), \(.*\...\).*/\2/" -e "s/ //g")
|
||
local diff1_5=$(echo -e "scale = scale ($one) \nx=$one - $five\n if (x>0) {print \"up\"} else {print \"down\"}\n print x \nquit \n" | bc)
|
||
loaddiff="$(echo -n "${one}${diff1_5}")"
|
||
|
||
# Count visible files:
|
||
let files=$(ls -l | grep "^-" | wc -l | tr -d " ")
|
||
let hiddenfiles=$(ls -l -d .* | grep "^-" | wc -l | tr -d " ")
|
||
let executables=$(ls -l | grep ^-..x | wc -l | tr -d " ")
|
||
let directories=$(ls -l | grep "^d" | wc -l | tr -d " ")
|
||
let hiddendirectories=$(ls -l -d .* | grep "^d" | wc -l | tr -d " ")-2
|
||
let linktemp=$(ls -l | grep "^l" | wc -l | tr -d " ")
|
||
if [ "$linktemp" -eq "0" ]
|
||
then
|
||
links=""
|
||
else
|
||
links=" ${linktemp}l"
|
||
fi
|
||
unset linktemp
|
||
let devicetemp=$(ls -l | grep "^[bc]" | wc -l | tr -d " ")
|
||
if [ "$devicetemp" -eq "0" ]
|
||
then
|
||
devices=""
|
||
else
|
||
devices=" ${devicetemp}bc"
|
||
fi
|
||
unset devicetemp
|
||
|
||
}
|
||
|
||
PROMPT_COMMAND=prompt_command
|
||
|
||
function pprom2 {
|
||
|
||
local BLUE="\[\033[0;34m\]"
|
||
local LIGHT_GRAY="\[\033[0;37m\]"
|
||
local LIGHT_GREEN="\[\033[1;32m\]"
|
||
local LIGHT_BLUE="\[\033[1;34m\]"
|
||
local LIGHT_CYAN="\[\033[1;36m\]"
|
||
local YELLOW="\[\033[1;33m\]"
|
||
local WHITE="\[\033[1;37m\]"
|
||
local RED="\[\033[0;31m\]"
|
||
local NO_COLOUR="\[\033[0m\]"
|
||
|
||
case $TERM in
|
||
xterm*)
|
||
TITLEBAR='\[\033]0;\u@\h:\w\007\]'
|
||
;;
|
||
*)
|
||
TITLEBAR=""
|
||
;;
|
||
esac
|
||
|
||
PS1="$TITLEBAR\
|
||
$BLUE[$RED\$(date +%H%M)$BLUE]\
|
||
$BLUE[$RED\u@\h$BLUE]\
|
||
$BLUE[\
|
||
$LIGHT_GRAY\${files}.\${hiddenfiles}-\
|
||
$LIGHT_GREEN\${executables}x \
|
||
$LIGHT_GRAY(\${TotalMeg}Mb) \
|
||
$LIGHT_BLUE\${directories}.\
|
||
\${hiddendirectories}d\
|
||
$LIGHT_CYAN\${links}\
|
||
$YELLOW\${devices}\
|
||
$BLUE]\
|
||
$BLUE[${WHITE}\${loaddiff}$BLUE]\
|
||
$BLUE[\
|
||
$WHITE\$(ps ax | wc -l | sed -e \"s: ::g\")proc\
|
||
$BLUE]\
|
||
\n\
|
||
$BLUE[$RED\$PWD$BLUE]\
|
||
$WHITE\$\
|
||
\
|
||
$NO_COLOUR "
|
||
PS2='> '
|
||
PS4='+ '
|
||
}
|
||
|
||
</code>
|
||
|
||
<sect1>Prompt Depending on Connection Type
|
||
|
||
<p>
|
||
Bradley M Alexander (storm@tux.org) had the excellent idea of reminding his
|
||
users what kind of connection they were using to his machine(s), so he
|
||
colour-codes prompts dependent on connection type. Here's the bashrc he
|
||
supplied to me:
|
||
|
||
<code>
|
||
|
||
# /etc/bashrc
|
||
|
||
# System wide functions and aliases
|
||
# Environment stuff goes in /etc/profile
|
||
|
||
# For some unknown reason bash refuses to inherit
|
||
# PS1 in some circumstances that I can't figure out.
|
||
# Putting PS1 here ensures that it gets loaded every time.
|
||
|
||
# Set up prompts. Color code them for logins. Red for root, white for
|
||
# user logins, green for ssh sessions, cyan for telnet,
|
||
# magenta with red "(ssh)" for ssh + su, magenta for telnet.
|
||
THIS_TTY=tty`ps aux | grep $$ | grep bash | awk '{ print $7 }'`
|
||
SESS_SRC=`who | grep $THIS_TTY | awk '{ print $6 }'`
|
||
|
||
SSH_FLAG=0
|
||
SSH_IP=`echo $SSH_CLIENT | awk '{ print $1 }'`
|
||
if [ $SSH_IP ] ; then
|
||
SSH_FLAG=1
|
||
fi
|
||
SSH2_IP=`echo $SSH2_CLIENT | awk '{ print $1 }'`
|
||
if [ $SSH2_IP ] ; then
|
||
SSH_FLAG=1
|
||
fi
|
||
if [ $SSH_FLAG -eq 1 ] ; then
|
||
CONN=ssh
|
||
elif [ -z $SESS_SRC ] ; then
|
||
CONN=lcl
|
||
elif [ $SESS_SRC = "(:0.0)" -o $SESS_SRC = "" ] ; then
|
||
CONN=lcl
|
||
else
|
||
CONN=tel
|
||
fi
|
||
|
||
# Okay...Now who we be?
|
||
if [ `/usr/bin/whoami` = "root" ] ; then
|
||
USR=priv
|
||
else
|
||
USR=nopriv
|
||
fi
|
||
|
||
#Set some prompts...
|
||
if [ $CONN = lcl -a $USR = nopriv ] ; then
|
||
PS1="[\u \W]\\$ "
|
||
elif [ $CONN = lcl -a $USR = priv ] ; then
|
||
PS1="\[\033[01;31m\][\w]\\$\[\033[00m\] "
|
||
elif [ $CONN = tel -a $USR = nopriv ] ; then
|
||
PS1="\[\033[01;34m\][\u@\h \W]\\$\[\033[00m\] "
|
||
elif [ $CONN = tel -a $USR = priv ] ; then
|
||
PS1="\[\033[01;30;45m\][\u@\h \W]\\$\[\033[00m\] "
|
||
elif [ $CONN = ssh -a $USR = nopriv ] ; then
|
||
PS1="\[\033[01;32m\][\u@\h \W]\\$\[\033[00m\] "
|
||
elif [ $CONN = ssh -a $USR = priv ] ; then
|
||
PS1="\[\033[01;35m\][\u@\h \W]\\$\[\033[00m\] "
|
||
fi
|
||
|
||
# PS1="[\u@\h \W]\\$ "
|
||
export PS1
|
||
alias which="type -path"
|
||
alias dir="ls -lF --color"
|
||
alias dirs="ls -lFS --color"
|
||
alias h=history
|
||
|
||
</code>
|
||
|
||
<sect1>A Prompt the Width of Your Term
|
||
|
||
<p>
|
||
A friend complained that he didn't like having a prompt that kept changing
|
||
size because it had $PWD in it, so I wrote this prompt that adjusts its
|
||
size to exactly the width of your term, with the working directory on the
|
||
top line of two.
|
||
|
||
<code>
|
||
|
||
#!/bin/bash
|
||
|
||
# termwide prompt
|
||
# by Giles - created 2 November 98
|
||
#
|
||
# The idea here is to have the upper line of this two line prompt
|
||
# always be the width of your term. Do this by calculating the
|
||
# width of the text elements, and putting in fill as appropriate
|
||
# or left-truncating $PWD.
|
||
#
|
||
|
||
function prompt_command {
|
||
|
||
TERMWIDTH=${COLUMNS}
|
||
|
||
# Calculate the width of the prompt:
|
||
|
||
hostnam=$(echo -n $HOSTNAME | sed -e "s/[\.].*//")
|
||
# "whoami" and "pwd" include a trailing newline
|
||
usernam=$(whoami)
|
||
let usersize=$(echo -n $usernam | wc -c | tr -d " ")
|
||
newPWD="${PWD}"
|
||
let pwdsize=$(echo -n ${newPWD} | wc -c | tr -d " ")
|
||
# Add all the accessories below ...
|
||
let promptsize=$(echo -n "--(${usernam}@${hostnam})---(${PWD})--" \
|
||
| wc -c | tr -d " ")
|
||
let fillsize=${TERMWIDTH}-${promptsize}
|
||
fill=""
|
||
while [ "$fillsize" -gt "0" ]
|
||
do
|
||
fill="${fill}-"
|
||
let fillsize=${fillsize}-1
|
||
done
|
||
|
||
if [ "$fillsize" -lt "0" ]
|
||
then
|
||
let cut=3-${fillsize}
|
||
newPWD="...$(echo -n $PWD | sed -e "s/\(^.\{$cut\}\)\(.*\)/\2/")"
|
||
fi
|
||
}
|
||
|
||
PROMPT_COMMAND=prompt_command
|
||
|
||
function termwide {
|
||
|
||
local GRAY="\[\033[1;30m\]"
|
||
local LIGHT_GRAY="\[\033[0;37m\]"
|
||
local WHITE="\[\033[1;37m\]"
|
||
local NO_COLOUR="\[\033[0m\]"
|
||
|
||
local LIGHT_BLUE="\[\033[1;34m\]"
|
||
local YELLOW="\[\033[1;33m\]"
|
||
|
||
case $TERM in
|
||
xterm*)
|
||
TITLEBAR='\[\033]0;\u@\h:\w\007\]'
|
||
;;
|
||
*)
|
||
TITLEBAR=""
|
||
;;
|
||
esac
|
||
|
||
PS1="$TITLEBAR\
|
||
$YELLOW-$LIGHT_BLUE-(\
|
||
$YELLOW\${usernam}$LIGHT_BLUE@$YELLOW\${hostnam}\
|
||
${LIGHT_BLUE})-${YELLOW}-\${fill}${LIGHT_BLUE}-(\
|
||
$YELLOW\${newPWD}\
|
||
$LIGHT_BLUE)-$YELLOW-\
|
||
\n\
|
||
$YELLOW-$LIGHT_BLUE-(\
|
||
$YELLOW\$(date +%H%M)$LIGHT_BLUE:$YELLOW\$(date \"+%a,%d %b %y\")\
|
||
$LIGHT_BLUE:$WHITE\$$LIGHT_BLUE)-\
|
||
$YELLOW-\
|
||
$NO_COLOUR "
|
||
|
||
PS2="$LIGHT_BLUE-$YELLOW-$YELLOW-$NO_COLOUR "
|
||
|
||
}
|
||
|
||
</code>
|
||
|
||
<sect1>The Elegant Useless Clock Prompt<label id="clock3">
|
||
|
||
<p>
|
||
This is one of the more attractive (and useless) prompts I've made.
|
||
Because many X terminal emulators don't implement cursor position save and
|
||
restore, the alternative when putting a clock in the upper right corner is
|
||
to anchor the cursor at the bottom of the terminal. This builds on the
|
||
idea of the "termwide" prompt above, drawing a line up the right side of
|
||
the screen from the prompt to the clock. A VGA font is required.
|
||
|
||
<p>Note: There is an odd substitution in here, that may not print properly
|
||
being translated from SGML to other formats: I had to substitute the screen
|
||
character for \304 - I would normally have just included the sequence
|
||
"\304", but it was necessary to make this substitution in this case.
|
||
|
||
<code>
|
||
|
||
#!/bin/bash
|
||
|
||
# This prompt requires a VGA font. The prompt is anchored at the bottom
|
||
# of the terminal, fills the width of the terminal, and draws a line up
|
||
# the right side of the terminal to attach itself to a clock in the upper
|
||
# right corner of the terminal.
|
||
|
||
function prompt_command {
|
||
# Calculate the width of the prompt:
|
||
hostnam=$(echo -n $HOSTNAME | sed -e "s/[\.].*//")
|
||
# "whoami" and "pwd" include a trailing newline
|
||
usernam=$(whoami)
|
||
newPWD="${PWD}"
|
||
# Add all the accessories below ...
|
||
let promptsize=$(echo -n "--(${usernam}@${hostnam})---(${PWD})-----" \
|
||
| wc -c | tr -d " ")
|
||
# Figure out how much to add between user@host and PWD (or how much to
|
||
# remove from PWD)
|
||
let fillsize=${COLUMNS}-${promptsize}
|
||
fill=""
|
||
# Make the filler if prompt isn't as wide as the terminal:
|
||
while [ "$fillsize" -gt "0" ]
|
||
do
|
||
fill="${fill}<7D>"
|
||
# The A with the umlaut over it (it will appear as a long dash if
|
||
# you're using a VGA font) is \304, but I cut and pasted it in
|
||
# because Bash will only do one substitution - which in this case is
|
||
# putting $fill in the prompt.
|
||
let fillsize=${fillsize}-1
|
||
done
|
||
# Right-truncate PWD if the prompt is going to be wider than the terminal:
|
||
if [ "$fillsize" -lt "0" ]
|
||
then
|
||
let cutt=3-${fillsize}
|
||
newPWD="...$(echo -n $PWD | sed -e "s/\(^.\{$cutt\}\)\(.*\)/\2/")"
|
||
fi
|
||
#
|
||
# Create the clock and the bar that runs up the right side of the term
|
||
#
|
||
local LIGHT_BLUE="\033[1;34m"
|
||
local YELLOW="\033[1;33m"
|
||
# Position the cursor to print the clock:
|
||
echo -en "\033[2;$((${COLUMNS}-9))H"
|
||
echo -en "$LIGHT_BLUE($YELLOW$(date +%H%M)$LIGHT_BLUE)\304$YELLOW\304\304\277"
|
||
local i=${LINES}
|
||
echo -en "\033[2;${COLUMNS}H"
|
||
# Print vertical dashes down the side of the terminal:
|
||
while [ $i -ge 4 ]
|
||
do
|
||
echo -en "\033[$(($i-1));${COLUMNS}H\263"
|
||
let i=$i-1
|
||
done
|
||
|
||
let prompt_line=${LINES}-1
|
||
# This is needed because doing \${LINES} inside a Bash mathematical
|
||
# expression (ie. $(())) doesn't seem to work.
|
||
}
|
||
|
||
PROMPT_COMMAND=prompt_command
|
||
|
||
function clock3 {
|
||
local LIGHT_BLUE="\[\033[1;34m\]"
|
||
local YELLOW="\[\033[1;33m\]"
|
||
local WHITE="\[\033[1;37m\]"
|
||
local LIGHT_GRAY="\[\033[0;37m\]"
|
||
local NO_COLOUR="\[\033[0m\]"
|
||
|
||
case $TERM in
|
||
xterm*)
|
||
TITLEBAR='\[\033]0;\u@\h:\w\007\]'
|
||
;;
|
||
*)
|
||
TITLEBAR=""
|
||
;;
|
||
esac
|
||
|
||
PS1="$TITLEBAR\
|
||
\[\033[\${prompt_line};0H\]
|
||
$YELLOW\332$LIGHT_BLUE\304(\
|
||
$YELLOW\${usernam}$LIGHT_BLUE@$YELLOW\${hostnam}\
|
||
${LIGHT_BLUE})\304${YELLOW}\304\${fill}${LIGHT_BLUE}\304(\
|
||
$YELLOW\${newPWD}\
|
||
$LIGHT_BLUE)\304$YELLOW\304\304\304\331\
|
||
\n\
|
||
$YELLOW\300$LIGHT_BLUE\304(\
|
||
$YELLOW\$(date \"+%a,%d %b %y\")\
|
||
$LIGHT_BLUE:$WHITE\$$LIGHT_BLUE)\304\
|
||
$YELLOW\304\
|
||
$LIGHT_GRAY "
|
||
|
||
PS2="$LIGHT_BLUE\304$YELLOW\304$YELLOW\304$NO_COLOUR "
|
||
|
||
}
|
||
|
||
</code>
|
||
|
||
</article>
|