Here are steps you can take to ensure that your bash scripts work as intended and are easy to update. Credit: Shutterstock / Media Whalestock Committing routine and even rarely required tasks to scripts is almost always a big win because you don’t have to reinvent the approach to getting work done each time it’s needed, and you save a lot of time on issues you handle often. Here are some tips for writing bash scripts and ensuring that they’ll be easy to use, easy to update/ and hard to misuse. Comments One important thing to do when you’re preparing a script on Linux is to add comments – especially for commands that might be a little complex. If you don’t run a script very often, comments can help ensure that you quickly grasp everything that it’s doing. If someone else has to use your scripts, the comments can make it a lot easier for them to know what to expect. So, always add comments. Even you might appreciate them! You don’t need to comment every line, just every significant group of commands. Here’s a simple example. #!/bin/bash # function to replace spaces in provided text with underscores replspaces () { echo $@ | sed 's/ /_/g' } # function to remove spaces from the provided text dropspaces () { echo $@ | sed 's/ //g'; } # commands to call the functions defined above replspaces "Hello World" replspaces `date` dropspaces "Hello World" dropspaces `date` The script above defines two functions: one to turn spaces into underscores and one to remove spaces altogether in whatever string is provided at the prompt. The comments say enough to explain this. Using functions As noted in the script above, functions can come in handy. This is especially true when a single script will run the functions many times. The scripts will be shorter and will be easier to understand. Verifying arguments Make a habit of having your scripts verify that the proper arguments have been provided by whomever runs them. You can check the number of arguments, but you can also verify that the responses are valid. For example, if you prompt for the name of a file, check that the file provided actually exists before running commands that attempt to use it. If it doesn’t exist, respond with an error and exit. The script below checks to ensure that two arguments have been provided as arguments to the script. If not, it prompts for the information needed. #!/bin/bash if [ $# -lt 2 ]; then echo "Usage: $0 lines filename" exit 1 else numlines=$1 filename=$2 fi … The script below prompts for a filename and then checks to see if the file exists. #!/bin/bash # get name of file to be read echo -n "filename> " read $filename # check that file exists or exit if [ ! -f $filename ]; then echo "No such file: $filename" exit fi If needed, you can also check whether the file is writable or readable. The version of the script below does both. #!/bin/bash # get name of file to be read echo -n "filename> " read filename # check that file exists or exit if [ ! -f $filename ]; then echo "No such file: $filename" exit else # determine if file is readable if [ ! -r $filename ]; then echo "$filename is not writable" exit fi # determine if file is writable if [ ! -w $filename ]; then echo "$filename is not readable" exit fi fi Note: The -r $filename check asks whether the file is readable. The ! -r $filename check asks whether it’s not readable. Exiting on errors You should almost always exit when an error is encountered when a script is run. Explain with an error message what went wrong. The set -o errexit will cause a script to exit regardless of what kind of error is encountered. #!/bin/bash set -o errexit # exit on ANY error tail NoSuchFile # tries to show bottom lines in NON-EXISTENT file echo -n "Enter text to be appended> " read txt echo $txt >> NoSuchFile The script above will exit if the “NoSuchFile” file doesn’t exist. An error will be displayed as well. To exit when a variable hasn’t been assigned a value (i.e., doesn’t exist), use the nounset option as shown in the script below. A set -u command works the same. #!/bin/bash # exit script if an unset variable is used set -o nounset # welcome user with a greeting echo $greeting echo -n "Enter name of file to be evaluated: " read filename If you run the script as is, you’ll run into the issue shown below and never be prompted for the file to be processed: $ ck_nounset ./ck_nounset: line 7: greeting: unbound variable Working with quotes In a lot of cases, it doesn’t matter if you use single quotes, double quotes, or no quotes at all. Putting quotes around a variable name in an if statement means that you won’t run into an error if the variable is not defined. The shell will never end up trying to evaluate the invalid command if [ = 2 ]. The command if [ “” = 2 ] is valid. if [ "$var" = 2 ] Putting quotes around arguments with more than one string is essential. You’d run into problems with the script below if the user answering the good/bad question entered “very good” instead of just “good” or “bad”. #!/bin/bash echo -n "Did you find the argument to be good or bad?> " read ans if [ $ans = good ]; then echo "Thank you for your feedback" else echo -n "What didn't you like?> " read ans echo $ans >> bad_feedback fi Instead, you could use a line like this to do the comparison. This would allow either “good” or “very good” as a response. if [[ "$ans" = *"good" ]]; then Using = or == Most of the time it makes no difference whether you use = or == to compare strings. However, some shells (e.g., dash) don’t work with ==, so save yourself the keystrokes and stick with = if you’re not sure. File permissions Make sure your scripts can be run by anyone who should be able to use them. A chmod -ug+rx filename command would give you (presumably the file owner) and anyone in the group associated with the file the ability to read and run the script. Test your scripts Don’t forget to spend some time testing to make sure your scripts do exactly what you intend. Testing can include things like failing to respond to the script’s prompts to see how it reacts. Wrap-Up Theres more advice about building reliable and easily maintainable scripts including learning to script on Linux using bash, many ways to loop using bash, and how to loop forever in bash. Read more bash tips: Checking exit codes in bash Using ‘break’ and ‘continue’ to exit loops in bash Incrementing and decrementing numeric variables in bash Bash: A primer for more effective use of the Linux bash shell Concatenating strings and using += in bash Related content how-to How to find files on Linux There are many options you can use to find files on Linux, including searching by file name (or partial name), age, owner, group, size, type and inode number. By Sandra Henry Stocker Jun 24, 2024 8 mins Linux opinion Linux in your car: Red Hat’s milestone collaboration with exida With contributions from Red Hat and critical collaborators, the safety and security of automotive vehicles has reached a new level of reliability. By Sandra Henry Stocker Jun 17, 2024 5 mins Linux how-to How to print from the Linux command line: double-sided, landscape and more There's a lot more to printing from the Linux command line than the lp command. Check out some of the many available options. By Sandra Henry Stocker Jun 11, 2024 6 mins Linux how-to Converting between uppercase and lowercase on the Linux command line Converting text between uppercase and lowercase can be very tedious, especially when you want to avoid inadvertent misspellings. Fortunately, Linux provides a handful of commands that can make the job very easy. By Sandra Henry Stocker Jun 07, 2024 5 mins Linux PODCASTS VIDEOS RESOURCES EVENTS NEWSLETTERS Newsletter Promo Module Test Description for newsletter promo module. Please enter a valid email address Subscribe