Unix: Writing more efficient shell scripts

Want to tune your shell scripts to run more efficiently? Let's check out a few changes that might help them run faster.

By  

Organize your tests such that you are likely to run only one test before reaching whatever conclusion lets your script take the next action. Find ways to skip over or quickly dispose of data that meets simple "can ignore" criteria.

When you can, put the most likely-to-fail test first in a compound AND.

if [[ $foo -eq 1 && $bar -eq 2 && $tmp -eq 3 ]]; then

Remember that AND tests require that all arguments be true, so the second and third tests won't even be run if the first test fails.

The same guidance applies to OR commands except that, for OR, any true condition makes the entire test true, so you'd want to put the most likely-to-pass test first.

if [[ $tmp -eq 3 || $bar -eq 2 || $foo -eq 1 ]]; then

Avoid putting commands in loops if they can be run once outside of loops. In other words, don't run commands multiple times if you can run them once and reuse the results. Run commands as few times as possible, especially commands that are not built-ins (internal to the shell).

$day=`date %A`			# <= here
while [ $stat != "end" ]
do
  case $day in ...
while [ $stat != "end" ]
do
  $day=`date %A`		# <= not here
  case $day in ...

If you have a choice between using a shell built-in and a standalone command, use the built-in. It will always be faster. Also avoid using full paths for commands. Since bash has built-ins for some commands you will find in /bin and /usr/bin (e.g., echo), avoiding the full path allows bash to use the built-ins that are available to it.

Another example of this is to use internal commands for math instead of commands such as expr.

$sum=$(( 11 + 11 ))
$sum=$(( $var1 + $var2 ))

While the time differences will be trivial for trivial scripts, they can make noticeable differences on complex scripts which run against large data collections. To view the differences between the way two scripts run, use the time command.

We can look at the difference that the ordering of the choices in a compound IF command with ANDed tests.

First, here's the script:

$ cat ex1
#!/bin/bash

echo -n "enter foo> "; read foo;
echo -n "enter bar> "; read bar;
echo -n "enter tmp> "; read tmp;

if [[ $foo -eq 1 && $bar -eq 2 && $tmp -eq 3 ]]; then
    echo ok
fi

And here's the timing:

$ time ex1
enter foo> 3
enter bar> 2
enter tmp> 1

real    0m2.950s
user    0m0.002s
sys     0m0.002s
$ time ex1
enter foo> 1
enter bar> 2
enter tmp> 3
ok

real    0m1.755s
user    0m0.000s
sys     0m0.003s

Notice how failing on the first AND test, the script runs in about 60% of the time it would take if it fails on the third test.

To make your scripts run quickly, you should also try to make the commands that you use as efficient as possible. Avoid unnecessary cat commands, unnecessary grep commands, unnecessary pipes, etc. whenever you can.

Photo Credit: 

fotolia

Join us:
Facebook

Twitter

Pinterest

Tumblr

LinkedIn

Google+

Answers - Powered by ITworld

ITworld Answers helps you solve problems and share expertise. Ask a question or take a crack at answering the new questions below.

Join us:
Facebook

Twitter

Pinterest

Tumblr

LinkedIn

Google+

Ask a Question
randomness