Like C programs, Shell scripts can be broken up into functions, which is more efficient than having multiple scripts calling each other (however, it does mean the function cannot be shared by different scripts).
e.g. A program to calculate how much space your web pages take up, as a percent of your total file space. Defines 2 functions, then uses them:
# percent $1 $2
# returns $1 as a percentage of $2
percent()
{
temp=`expr $1 \* 100`
expr $temp / $2
}
# sizeof dir
# returns size of all files in dir and below
sizeof()
{
cd $1
du | grep '\.$' | cut -f1
}
web=`sizeof $HOME/public_html`
echo $web
total=`sizeof $HOME`
echo $total
ans=`percent $web $total`
echo "Your web files are $ans% of your total files."
By default, functions have access to the caller's environment variables without exporting:
fn()
{
echo $x
}
x=3
fn
Whereas if we call a separate script,
it does not by default have access to the caller's
environment variables.
You can pipe to functions too (in general you can treat them just like a separate program).
Consider a program:
# killstring (string) # kills all instances of program named by string # e.g. # killstring textedit # kills all your textedit processesIf "killstring" first tries to identify these processes:
ps -fu $USER | grep -i $1when you type "killstring textedit" you get something like:
humphrys 28414 28413 0 12:32:50 pts/5 0:00 grep -i textedit humphrys 28396 1 0 12:32:19 pts/23 0:00 textedit -geometry 600x600+200-100 f1 humphrys 28352 1 0 12:31:51 pts/23 0:00 textedit -geometry 600x600+200-100 f2 humphrys 28366 1 0 12:31:51 pts/23 0:00 textedit -geometry 600x600+200-100 f3 humphrys 28413 28073 0 12:32:50 pts/5 0:00 /bin/sh killstring texteditso we need to strip out killstring itself, and the grep itself. We also have a number of unwieldy lines of text, which we want to process 1 by 1, to extract the process ID and kill it. We can do this by piping to a function. So killstring looks like:
fn()
{
while read user pid restofline
do
kill $pid
done
}
ps -fu $USER | grep -i $1 | grep -v $0 | grep -v "grep -i $1" | fn