Bash Bad Substitution Syntax Error: Simple and Quick Fixes (2023)

Sometimes while writing a Bash script I have seen the Bad substitution syntax error and looking at forums I realised that I’m not alone, other people are seeing the same error too.

What is the Bash bad substitution error?

It’s a syntax error that occurs when you execute your Bash script and it can be caused by different reasons. Two common causes for this error are the incorrect use of command substitution and incorrect characters added to the lines of your script (for example extra dollar signs or white spaces).

We will go through some examples of scripts in which this error occurs, in this way you will know how to fix the bad substitution error when you see it in your scripts.

At the end of this guide I also have a nice exercise for you to test your knowledge.

Let’s get started!

Table of Contents

Bad Substitution Error Related to Command Substitution

One circumstance in which this error occurs is when you want to use command substitution but by mistake you use curly braces instead of parentheses.

Command substitution allows to store the output of a Bash command (as complex as you want) into a variable. It allows to build very flexible and powerful Bash scripts.

I have created a very simple script to show you how the bad substitution error occurs with an incorrect use of command substitution.

I want to use command substitution to store the output of the command ls -al in the variable OUTPUT.

#!/bin/bashOUTPUT=${ls -al}echo "$OUTPUT"

When I execute the script I see the following output:

(localhost)$ ./subst.sh./subst.sh: line 3: ${ls -al}: bad substitution

What’s wrong with my script?

According to the error there’s something wrong at line 3 of the script, I have used the wrong type of brackets…..

I have used ${ } around the ls command, instead command substitution requires $( ) around the command.

Let’s replace the parentheses with curly brackets and then rerun the script:

#!/bin/bashOUTPUT=$(ls -al)echo "$OUTPUT"

Now the output is:

(localhost)$ ./subst.shtotal 8drwxr-xr-x 4 myuser mygroup 128 Jul 26 12:57 .drwxr-xr-x 29 myuser mygroup 928 Jul 26 12:54 ..-rwxr-xr-x 1 myuser mygroup 45 Jul 26 12:56 subst.sh-rw-r--r-- 1 myuser mygroup 0 Jul 26 12:55 testfile

This time the script works well, we have fixed the bad substitution error.

Let’s look at other reasons for the same syntax error…

Bad Substituion Error Caused by White Spaces

The cause of this error can also be the presence of white spaces in our code that go against Bash syntax. These white spaces cause syntax errors in the way I will show you below…

I have modified the last line of the script we have created in the previous section:

#!/bin/bashOUTPUT=$(ls -al)echo "${OUTPUT }"

I have added curly brackers around the OUTPUT variable and by mistake I have added a white space before closing the curly bracket.

When I run the script I get the following error from the Linux shell:

(localhost)$ ./subst.sh./subst.sh: line 4: ${OUTPUT }: bad substitution

The error message clearly tells the line that is causing the error.

To solve the problem we can just remove the white space before the closing curly brackets.

Make sure you verify any incorrect white spaces in your code if you get the bad substitution error.

Dollar Sign Used Twice When Printing the Value of a Variable

Another common cause for this error is using the dollar sign twice when you print the value of a variable in your script.

Here is the script used previously, but modified to introduce a syntax error in the last line:

#!/bin/shOUTPUT=$(ls -al)echo "${$OUTPUT}"

As you can see I have used the $ sign twice in the line where I use the echo command.

The error from the script is:

(localhost)$ ./subst.sh./subst.sh: line 4: ${$OUTPUT}: bad substitution

The solution is to remove the extra $ sign inside the curly brackets.

Let’s see what happens if we have multiple variables of type string in our echo command…

Bad Substitution Error and String Variables

In the next script we will print in the shell the full path of a directory created from the concatenation of three different variables: BASE_DIR, APP_DIR and CONF_DIR.

#!/bin/bashBASE_DIR=/opt/baseAPP_DIR=appCONF_DIR=confecho ${$BASE_DIR/$APP_DIR/$CONF_DIR}

The code looks correct, let’s run it!

(localhost)$ ./full_path.sh./full_path.sh: line 6: ${$BASE_DIR/$APP_DIR/$CONF_DIR}: bad substitution

What’s causing the bad substitution error?

We are seeing a similar error to the one in the previous section, caused by an extra dollar sign that the Bash shell doesn’t like.

The difference between this script and the previous one is that in the previous script we only had one variable within curly brackets.

Let’s see how we can fix the error in this script…

Option 1: Remove the outer $ sign in the last line:

#!/bin/bashBASE_DIR=/opt/baseAPP_DIR=appCONF_DIR=confecho $BASE_DIR/$APP_DIR/$CONF_DIR

If I run the script the output is:

(localhost)$ ./full_path.sh/opt/base/app/conf

The script works well!

Option 2: We will keep the outer $ sign and remove the dollar sign immediately before the BASE_DIR variable:

#!/bin/bashBASE_DIR=/opt/baseAPP_DIR=appCONF_DIR=confecho ${BASE_DIR/$APP_DIR/$CONF_DIR}

This time the scripts prints in the shell…

(localhost)$ ./full_path.sh/opt/base

The output is incorrect, the values of APP_DIR and CONF_DIR are missing.

Here is another possible option:

#!/bin/bashBASE_DIR=/opt/baseAPP_DIR=appCONF_DIR=confecho ${BASE_DIR}/${APP_DIR}/${CONF_DIR}

And the output is correct:

(localhost)$ ./full_path.sh/opt/base/app/conf

I definitely prefer this version because the three variables are clearly separated and this helps us avoid errors in the script.

Bash Bad Substitution When Converting String Variables to Uppercase or Lowercase

Converting strings in your Bash script from lowercase to uppercase (or viceversa) is a common requirement.

Recent versions of Bash (e.g. here I’m using Bash 4.4.19) provide a built-in way for uppercasing and lowercasing strings.

Here’s how…

[myuser@localhost ~]$ DAY=monday[myuser@localhost ~]$ echo ${DAY}monday[myuser@localhost ~]$ echo ${DAY^}Monday[myuser@localhost ~]$ echo ${DAY^^}MONDAY

A similar syntax but with , instead of ^ allows to convert strings from uppercase to lowercase:

[myuser@localhost ~]$ DAY=MONDAY[myuser@localhost ~]$ echo ${DAY}MONDAY[myuser@localhost ~]$ echo ${DAY,}mONDAY[myuser@localhost ~]$ echo ${DAY,,}monday

Now let’s try to run this with an earlier version of Bash. Before I was running it on Linux, now let’s try with the Bash shell on Mac:

(localhost)$ bash --versionGNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)Copyright (C) 2007 Free Software Foundation, Inc.

Here is the error I get when I try to convert the string variable to uppercase:

(localhost)$ DAY=monday(localhost)$ echo ${DAY}monday(localhost)$ echo ${DAY^}-bash: ${DAY^}: bad substitution(localhost)$ echo ${DAY^^}-bash: ${DAY^^}: bad substitution

In both cases we receive a “bad substitution” error because this version of the Bash shell doesn’t support this syntax.

So, how can I convert this string into uppercase?

The alternative with this version of Bash is using the tr command:

(localhost)$ DAY=monday(localhost)$ echo "$DAY" | tr '[:lower:]' '[:upper:]'MONDAY

Makes sense?

Fix the Bad Substitution Error: A Simple Exercise

We are almost at the end of this guide and to make sure you now know how to fix the bad substitution error, I want to give you a simple exercise.

I have created a small script called archive.sh that creates a tar archive of the files in the current directory.

#!/bin/bashARCHIVE_NAME=archive.tar.gztar cvzf ${$ARCHIVE_NAME} .if [ $? -eq 0 ]; then ARCHIVE_SIZE=${ls -al archive.tar.gz | awk '{print $5}'} echo "Archive created successfully. The size of the archive is $ARCHIVE_SIZE"fi

But something doesn’t go well when I run it:

[myuser@localhost]$ ./archive.sh./archive.sh: line 4: ${$ARCHIVE_NAME}: bad substitution

Can you see what is causing the error?

Try to fix the script and rerun it to make sure the bad substitution error disappears.

Also, have a look at this guide about the tar command if you want to learn more about it.

Conclusion

In this guide I have explained the most common causes for the Bash bad substitution syntax error and you now have different ways to understand why this error occurs and to fix it.

This error could be due to:

  • Incorrect ways of using command substitution.
  • Unexpected white spaces within commands.
  • Too many dollar signs when referring to variables.
  • A Bash version that don’t support specific features like lowercasing and uppercasing.

Does the error you are seeing in your script fit one of the scenarios above?

Let me know which one if it does, and if it doesn’t let me know about the error you are seeing in the comments below 🙂

Related FREE Course: Decipher Bash Scripting

Related posts:

How to Replace a String in a File Using BashBash Syntax Error Near Unexpected Token: How to Fix ItBash Script Arguments: How to Pass Them via the Command Line

Bash Bad Substitution Syntax Error: Simple and Quick Fixes (1)

Claudio Sabato

I’m a Tech Lead, Software Engineer and Programming Coach. I want to help you in your journey to become a Super Developer!

Top Articles
Latest Posts
Article information

Author: Amb. Frankie Simonis

Last Updated: 03/29/2023

Views: 6030

Rating: 4.6 / 5 (56 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Amb. Frankie Simonis

Birthday: 1998-02-19

Address: 64841 Delmar Isle, North Wiley, OR 74073

Phone: +17844167847676

Job: Forward IT Agent

Hobby: LARPing, Kitesurfing, Sewing, Digital arts, Sand art, Gardening, Dance

Introduction: My name is Amb. Frankie Simonis, I am a hilarious, enchanting, energetic, cooperative, innocent, cute, joyous person who loves writing and wants to share my knowledge and understanding with you.