Bash Intro
Basic Commands
Bourne-Again Shell (bash) is one of the better if not best command line shells. It's built off the old shell (sh) but has features from Korn and C (tsh) shells as well. Some basic things with bash will make life better for you to know. First and foremost is expansion. When a command is given to the shell, it looks for things to expand. As an example lets look at these two examples.
NOTE: in examples you might notice a $ or # at the start of the command. These usually mean $ for normal user account and # for "root". You do not type these in, they are just there to show you who should be running the commands.$ echo *
Now this simple looking command shows how dangerous expansion can be when not used correctly. If the command is issued inside a directory with files or directories then bash expands it into something like this before it runs.
echo mydir myfile1 secondfile thirdfile
In this example, the directory listing is passed to echo as an space seperated list. However if you run the same command in a directory without files then bash looks, can't expand the '*' and passes it to echo and you get this result.
echo *
Of course, with echo it doesn't make much difference but somethins this can be a very bad thing. If for example, you were trying to issue a remote command, or pass an * to a command, bash would expand that to any matching files/directories you have locally.
Simple Scripts
Bash scripting can make life very easy for the user. Say for example, you had a directory of webpages. Your webmaster left, and the old address is no longer bob@foobar.com. Short of opening up EACH and every file one at a time this could be a long and painful process. Bash to the rescue! We can use a compound statement and do it all in ONE line. The first line of a script should be #!/path/bash to tell where your bash is, usuall /bin/bash. You can run it two ways. bash myscript.sh OR ./myscript.sh providing you did a chmod +x myscript.sh first. Also anything after a pound or '#' character are comments. To make it easy to read I'll start by showing the script in multi-line format with tabs.
#!/bin/bash # for loop for each file in '*.html' or all html files in the dir for i in *.html do # simple sed replace but output to a new file sed 's/bob@foobar.com/webmaster@foobar.com/' $i > $i.new # replace the new file over the old one mv -f $i.new $i done
Now note that we have to redirect the stdout to a new filename because if you just use > $i then bash will erase the file before sed can process it and you will have all blank files. Now for the single inline version.
$ for i in *.html; do sed 's/bob@foobar.com/webmaster@foobar.com/' $i > $i.new; mv -f $i.new $i; done
Nothing really special here except note that we do not put a semicolon after the do line. That's it, and in a few seconds all your .html pages will have the new address. As another note, I would suggest next time using webmaster and then update /etc/aliases instead. *grin*
Variables
You can set your own variables to store information in by using this syntax.
MYVAR=value
It is important to NOT have a space between the equal sign and the name/value. As a more real world example, lets use bash to make a filename for us using the current date.
#!/bin/bash DATE=`date +'%m-%d-%Y'` echo $DATE
In this example, the variable DATE is set using the command date with formatting. This would result in something like "01-01-2003". Lets say you wanted to make your filename be a more then just the date. We can use the {} braces to tell bash where the variable name starts and stops.
#!/bin/bash
DATE=`date +'%m-%d-%Y'`
echo ${DATE}today
Without the braces, bash would think we wanted the variable $DATEtoday and output nothing. This example gives us "01-01-2003today" like we wanted. You don't have to use braces, but they come in handy sometimes to show the start/stop of a variable.
Bash also includes special variables that expand into many useful information. Below is a short list of the more common ones
$$ = current pid !$ = lass command issued $? = error code of lass command $0 = command $1 = argument #1, also $2,$3,$4, etc. @ = full command line $_ = current shell
Job Control
You don't always have to run things and wait for them to complete. You can run a job in the background, or even suspend a running job. To do this, we use $ % & fg bgi jobs. A few examples
# run a full directory listing in the background $ ls /* &
You can if you run the last command without a & symbol, it will start dumping all your files out to screen. You can then press ctrl-<z> and it will show the job as susspended. At this point you can one of two things. Either bring it to the foreground and continue it, or put it into the background and let it finish.
# bring job 1 to the foreground $ fg %1 # OR to send to background and run $ bg %1
As another note you can issue a kill %1 to kill job #1 too. Type 'jobs' for the list that is currently open. Note bash will complain if you have jobs open and try and log out.
And don't ever forget that good old man page! man bash
Multi-color-term.sh
Here is a real world example of a bash script I use to change terminal colors for aterm, mrxvt, and eterm. To use, just put in your ~/bin and symlink all the terms you want to use. IE:
ln -s ~/bin/multi-color-term.sh ~/bin/aterm.
#!/bin/bash
# Term color changing program.
# Copyright 2005 by Greg Watson <gwatson@linuxlogin.com>
# GPL-2 License - Enjoy!
# File used to keep track of the current last color
TINTFILE=$HOME/.term-tint.last
TERMPATH=/usr/bin
# You can use either `basename $0` and just make symlinks
# or change this to your term cmd, such as mrxvt or aterm
RUNTERM=`basename $0`
if [ -f $TINTFILE ]; then
TINTVAL=`cat $TINTFILE`
CLRCODE=`eval expr "$TINTVAL + 1"`
if [ "$CLRCODE" -gt "8" ]; then
CLRCODE=0;
fi
else
CLRCODE="0"
fi
# update the file
echo "$CLRCODE" > $TINTFILE
{ [ "$CLRCODE" -eq "0" ] && CLRNAME="-tint blue "; } ||
{ [ "$CLRCODE" -eq "1" ] && CLRNAME="-tint red "; } ||
{ [ "$CLRCODE" -eq "2" ] && CLRNAME="-tint green "; } ||
{ [ "$CLRCODE" -eq "3" ] && CLRNAME="-tint cyan "; } ||
{ [ "$CLRCODE" -eq "4" ] && CLRNAME="-tint magenta"; } ||
{ [ "$CLRCODE" -eq "5" ] && CLRNAME="-tint orange"; } ||
{ [ "$CLRCODE" -eq "6" ] && CLRNAME="-tint purple"; } ||
{ [ "$CLRCODE" -eq "7" ] && CLRNAME="-tint skyblue"; } ||
{ [ "$CLRCODE" -eq "8" ] && CLRNAME="-tint yellow "; }
exec $TERMPATH/$RUNTERM $CLRNAME $@
Download multi-color-term.shDownload urxvt.sh (rxvt-unicode with true transparency)







