Scripting in Bash, like sculpting in clay, starts with the simplest elemental commands, growing gradually into intricate systems that can automate complex tasks with elegance and precision. The power of Bash scripting is found in its simplicity combined with capabilities that touch almost every peripheral task possible on UNIX-like machines1.
“Bash is a superset of the Bourne Shell and includes virtually all its features."2 This statement, quoted from Michael Hartl’s book, explains well why Bash is admired. But what elevates bash scripting to the next level is its bevy of advanced techniques and concepts. This article will plunge into these depths, revealing pearls of wisdom necessary to master this art.
Conditionals and Tests
Before we march further, Let’s begin with a necessary refresher on conditionals. In common parlance, these are IF-THEN-ELSE constructs. Bash provides a plethora of conditionals but stands out with its built-in ‘test’ construct3. Below is a simple demonstration:
if test -f "/etc/passwd"
then
echo "File exists."
else
echo "File not found."
fi
Functions
While bash scripting, it’s usual to repeat a particular task within different scripts or even within the same script. Functions are a convenient way to bundle such tasks. They operate as any other command within your command path, accepting inputs and providing outputs4.
#!/bin/bash
# Function definition
greeting() {
echo "Hello, ${1}"
}
# Call the function
greeting "John Doe"
I/O Redirection
Next, we delve into I/O Redirection, an advanced feature of UNIX-like systems. This capability allows us to redirect standard input/output/error (STDIN/STDOUT/STDERR) of a command5. Here’s a quick example:
# redirect STDOUT to a file
command > file
# redirect STDERR to a file.
command 2> file
# redirect STDOUT and STDERR to a file
command &> file
Parameter Expansion
Parameter Expansion is another power-tool in your bash scripting toolkit6. It allows you to manipulate the value of a parameter within the shell, saving you a system call. Here’s a straightforward demonstration:
#!/bin/bash
name="John_Doe"
# Now, let's replace the underscore with a space
echo ${name/_/ }
Process Substitution
Meet Process Substitution, the bash scripting feature that lets you use the output of a command as if it were a file7. Here’s how it looks in action:
# counting number of lines in multiple files
wc -l <(ls /etc/passwd) <(ls /etc/group)
Co-Processes
Sharing data between a script and a command is challenging unless you master Co-Processes. Co-Processes allow us to bi-directionally move data between processes8. Savvy use of this, however, does require an understanding of file descriptor manipulation9.
#!/bin/bash
coproc my_coproc { awk '{print $1}' ; }
echo "John Doe" >&${my_coproc[1]}
read name <&${my_coproc[0]}
echo "First name is: ${name}"
Gotchas & Pitfalls
Being habitual users of ‘bash’, we sometimes take things for granted. Have you ever, for instance, considered the possiblity of filenames with spaces causing problems?10
# This will fail if files have spaces in name
for file in $(ls); do
mv "${file}" "${file}.old"
done
Instead, consider using safer alternatives like:
# A safer alternative
for file in *; do
mv "${file}" "${file}.old"
done
Wrapping it up, the well-quoted line from Buckys C++ Programming Tutorials holds true here as well - “The more you learn, the more you realize how much you don’t know."11. With bash scripting, the depth of knowledge grows alongside your skill, drawing you deeper into this fascinating world. Happy scripting!
Cooper Mendel. Pro Bash Programming: Scripting the UNIX/Linux Shell, Second Edition. Apress, 2019. ↩︎
Michael Hartl. Learn Enough Command Line To Be Dangerous. Learn Enough, 2020. ↩︎
McCarthy Jim. Bash by Example, Part 1. IBM, 2000. ↩︎
Barman Kanak. Bash Guide for Beginners. Linux Documentation Project, 2004. ↩︎
Downs Brian, Castagna Jarkko, Interlandi Nic. Korn Shell Programming. Addison-Wesley, 1997. ↩︎
Newham Cameron, Rosenblatt Bill. Learning the bash Shell. O’Reilly Media, 1998. ↩︎
Parker Steve. Shell Scripting Tutorial. Shell Scripting Tutorial, 2010. ↩︎
Parker Steve. Co-Processes. Shell Scripting Tutorial, 2010. ↩︎
Kaiser Karl Michael. Advanced Bash-Scripting Guide. Linux Documentation Project, 2008. ↩︎
Gray Michael. Common bash pitfalls and good practices. Red Hat, 2020. ↩︎
Bucky Roberts. Buckys C++ Programming Tutorials. thethenewboston, 2011. ↩︎