Most shell scripts are quick 'n dirty solutions to non-complex problems. As such, optimizing them for speed is not much of an issue. Consider the case, though, where a script carries out an important task, does it well, but runs too slowly. Rewriting it in a compiled language may not be a palatable option. The simplest fix would be to rewrite the parts of the script that slow it down. Is it possible to apply principles of code optimization even to a lowly shell script?
Check the loops in the script. Time consumed by repetitive operations adds up quickly. If at all possible, remove time-consuming operations from within loops.
Use builtin commands in preference to system commands. Builtins execute faster and usually do not launch a subshell when invoked.
Avoid unnecessary commands, particularly in a pipe.
cat "$file" | grep "$word"
grep "$word" "$file"
# The above command-lines have an identical effect,
#+ but the second runs faster since it launches one fewer subprocess.
command seems especially prone to overuse in scripts.
Certain operators, notably expr, are very inefficient and might be replaced by double parentheses arithmetic expansion. See Example A-59.
math via $(( ))
math via expr:
real 1m17.879s # Much slower!
math via let:
Condition testing constructs in scripts deserve close scrutiny. Substitute case for if-then constructs and combine tests when possible, to minimize script execution time. Again, refer to Example A-59.
Test using "case" construct:
Test with if , no quotes:
Test with if , quotes:
Test with if , using -eq:
Erik Brandsberg recommends using associative arrays in preference to conventional numeric-indexed arrays in most cases. When overwriting values in a numeric array, there is a significant performance penalty vs. associative arrays. Running a test script confirms this. See Example A-60.
Assigning a simple variable
Assigning a numeric index array entry
Overwriting a numeric index array entry
Linear reading of numeric index array
Assigning an associative array entry
Overwriting an associative array entry
Linear reading an associative array entry
Assigning a random number to a simple variable
Assigning a sparse numeric index array entry randomly into 64k cells
Reading sparse numeric index array entry
Assigning a sparse associative array entry randomly into 64k cells
Reading sparse associative index array entry
Use the time and times tools to profile computation-intensive commands. Consider rewriting time-critical code sections in C, or even in assembler.
Try to minimize file I/O. Bash is not particularly efficient at handling files, so consider using more appropriate tools for this within the script, such as awk or Perl.
Write your scripts in a modular and coherent form, so they can be reorganized and tightened up as necessary. Some of the optimization techniques applicable to high-level languages may work for scripts, but others, such as loop unrolling, are mostly irrelevant. Above all, use common sense.
For an excellent demonstration of how optimization can dramatically reduce the execution time of a script, see Example 16-47.