[bash] When do we need curly braces around shell variables?

In shell scripts, when do we use {} when expanding variables?

For example, I have seen the following:

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable

Is there a significant difference, or is it just style? Is one preferred over the other?

This question is related to bash shell syntax curly-braces

The answer is


Curly braces are always needed for accessing array elements and carrying out brace expansion.

It's good to be not over-cautious and use {} for shell variable expansion even when there is no scope for ambiguity.

For example:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_arch       # {} is needed since _ can be a part of shell variable name

So, it is better to write the three lines as:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

which is definitely more readable.

Since a variable name can't start with a digit, shell doesn't need {} around numbered variables (like $1, $2 etc.) unless such expansion is followed by a digit. That's too subtle and it does make to explicitly use {} in such contexts:

set app      # set $1 to app
fruit=$1le   # sets fruit to apple, but confusing
fruit=${1}le # sets fruit to apple, makes the intention clear

See:


You are also able to do some text manipulation inside the braces:

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

Result:

./folder/subfolder/file.txt ./folder

or

STRING="This is a string"
echo ${STRING// /_}

Result:

This_is_a_string

You are right in "regular variables" are not needed... But it is more helpful for the debugging and to read a script.


The end of the variable name is usually signified by a space or newline. But what if we don't want a space or newline after printing the variable value? The curly braces tell the shell interpreter where the end of the variable name is.

Classic Example 1) - shell variable without trailing whitespace

TIME=10

# WRONG: no such variable called 'TIMEsecs'
echo "Time taken = $TIMEsecs"

# What we want is $TIME followed by "secs" with no whitespace between the two.
echo "Time taken = ${TIME}secs"

Example 2) Java classpath with versioned jars

# WRONG - no such variable LATESTVERSION_src
CLASSPATH=hibernate-$LATESTVERSION_src.zip:hibernate_$LATEST_VERSION.jar

# RIGHT
CLASSPATH=hibernate-${LATESTVERSION}_src.zip:hibernate_$LATEST_VERSION.jar

(Fred's answer already states this but his example is a bit too abstract)


Variables are declared and assigned without $ and without {}. You have to use

var=10

to assign. In order to read from the variable (in other words, 'expand' the variable), you must use $.

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

This has confused me sometimes - in other languages we refer to the variable in the same way, regardless of whether it's on the left or right of an assignment. But shell-scripting is different, $var=10 doesn't do what you might think it does!


You use {} for grouping. The braces are required to dereference array elements. Example:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect

Following SierraX and Peter's suggestion about text manipulation, curly brackets {} are used to pass a variable to a command, for instance:

Let's say you have a sposi.txt file containing the first line of a well-known Italian novel:

> sposi="somewhere/myfolder/sposi.txt"
> cat $sposi

Ouput: quel ramo del lago di como che volge a mezzogiorno

Now create two variables:

# Search the 2nd word found in the file that "sposi" variable points to
> word=$(cat $sposi | cut -d " " -f 2)

# This variable will replace the word
> new_word="filone"

Now substitute the word variable content with the one of new_word, inside sposi.txt file

> sed -i "s/${word}/${new_word}/g" $sposi
> cat $sposi

Ouput: quel filone del lago di como che volge a mezzogiorno

The word "ramo" has been replaced.


Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to syntax

What is the 'open' keyword in Swift? Check if returned value is not null and if so assign it, in one line, with one method call Inline for loop What does %>% function mean in R? R - " missing value where TRUE/FALSE needed " Printing variables in Python 3.4 How to replace multiple patterns at once with sed? What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript? How can I fix MySQL error #1064? What do >> and << mean in Python?

Examples related to curly-braces

CURL to pass SSL certifcate and password What is the meaning of curly braces? When do we need curly braces around shell variables? How can I print literal curly-brace characters in a string and also use .format on it? Is it a bad practice to use an if-statement without curly braces? Go to Matching Brace in Visual Studio? Eclipse jump to closing brace