Advanced Bash Scripting

Conventions

Expanding

In shell scripting, variable expansion uses the dollar sign ($) to tell the shell to replace the variable name with its stored value.

#!/bin/bash
var="value of var"
echo ${var}

Running this script:

$ ./var-sample.sh
value of var

Braces vs No Braces

You can reference variables with or without braces. Braces become essential when you append characters immediately after the variable name.

With Braces

#!/bin/bash
var="value of var"
echo ${var}

Without Braces

#!/bin/bash
var="value of var"
echo $var

Both scripts output:

$ ./var-sample.sh
value of var

Delimiting Variable Names

Without braces, the shell cannot determine where the variable name ends:

#!/bin/bash
height=170

# Incorrect: $heightcm is undefined
echo "Your height is = $heightcm"

# Correct: ${height}cm expands properly
echo "Your height is = ${height}cm"
$ ./height.sh
Your height is = 
Your height is = 170cm

Quoting and Word Splitting

By default, unquoted expansions are split on whitespace defined by IFS (space, tab, newline). Use quotes to preserve the exact value.

The image illustrates how different whitespace characters (tabs, spaces, linebreaks) affect the formatting of a string variable containing "Hello World".

Unquoted Expansion

#!/bin/bash
string="One Two Three"

# Splits into words
for element in ${string}; do
  echo "${element}"
done

Quoted Expansion

#!/bin/bash
string="One Two Three"

# Preserves the entire string as one element
for element in "${string}"; do
  echo "${element}"
done
$ ./string.sh
One
Two
Three

$ ./string2.sh
One Two Three

Note

Always quote expansions when dealing with filenames, paths, or URLs to prevent unintended splitting.

Intentional Splitting

Sometimes you want to iterate over each word in a list:

#!/bin/bash
readonly SERVERS="server1 server2 server3"

for server in ${SERVERS}; do
  echo "${server}.example.com"
done
$ ./expanding.sh
server1.example.com
server2.example.com
server3.example.com

Quoting the variable in this case treats the entire list as one element:

#!/bin/bash
readonly SERVERS="server1 server2 server3"

for server in "${SERVERS}"; do
  echo "${server}.example.com"
done
$ ./expanding2.sh
server1 server2 server3.example.com

Best Practices

Use this quick reference to decide when to quote or brace variables:

ScenarioQuotingBracesExample
Simple expansionOptionalOptionalecho $var
Appending text to a variableOptionalRequiredecho "${var}suffix"
File paths and filenamesRecommendedOptionalls "${directory}/file.txt"
URLs and complex stringsRecommendedOptionalcurl "${URL}?id=123&name=abc"
Iterating over words intentionallyOptionalOptionalfor x in ${list}; do ...; done
Preventing word splittingRequiredOptionalread -r line <<< "${input}"

The image is a slide titled "Expanding Variables" with checkmarks next to "Directory paths, filenames" and "Assigning URLs to variables."

Warning

Never rely on unquoted variable expansions for user input or file names—they can introduce security risks or unexpected behavior.

Further Reading

Watch Video

Watch video content

Previous
Functions