- shell string bad substitution
- 3 Answers 3
- Bash Bad Substitution Syntax Error: Simple and Quick Fixes
- Bad Substitution Error Related to Command Substitution
- Bad Substituion Error Caused by White Spaces
- Dollar Sign Used Twice When Printing the Value of a Variable
- Bad Substitution Error and String Variables
- Bash Bad Substitution When Converting String Variables to Uppercase or Lowercase
- Fix the Bad Substitution Error: A Simple Exercise
- Conclusion
shell string bad substitution
However I got the Bad substitution error from the compiler. And when I mention about ‘shell’.I just talking about shell for I don’t know the difference between bash or the others.I just using Ubuntu 10.04 and using the terminal. (I am using bash.)
what is your argument to the script, i.e. the value of $1? Please edit this information INTO your message above, and not as a reply to my comment. try surrounding all references to $1 in dbl-quotes, i.e. echo «$1» , etc. Good luck!
They are different shells that implement different features. Even if /bin/sh is bash, it is executed as if —posix was used, which disables some bash features.
3 Answers 3
If your shell is a sufficiently recent version of bash , that parameter expansion notation should work.
In many other shells, it will not work, and a bad substitution error is the way the shell says ‘You asked for a parameter substitution but it does not make sense to me’.
#! /bin/sh length=echo `expr index "$1" .zip` a=$1 echo $(a:0:length>
The second line exports variable length with value echo for the command that is generated by running expr index «$1» .zip . It does not assign to length . That should be just:
where the $ notation generates an error if $1 is not set (if the script is invoked with no arguments).
Note that if $1 holds filename.zip , the output of expr index $1 .zip is 2, because the letter i appears at index 2 in filename.zip . If the intention is to get the base name of the file without the .zip extension, then the classic way to do it is:
and the more modern way is:
There is a difference; if the name is /path/to/filename.zip , the classic output is filename and the modern one is /path/to/filename . You can get the classic output with:
Or, in the classic version, you can get the path with:
base=$(dirname $1)/$(basename $1 .zip)`.)
If the file names can contain spaces, you need to think about using double quotes, especially in the invocations of basename and dirname .
@Simon: it works for me with Bash 3.2.51 (provided with Mac OS X 10.9.2 Mavericks). It also works with Bash 4.2.25 (provided with Ubuntu 12.04). For example: AZ=abcdefghijklmnopqrstuvwxyz; echo $
Thanks for the fast answer. Actually AZ=abcdefghijklmnopqrstuvwxyz; echo $
@Simon: now that is a curious state of affairs. I guess you’re going to need to track down what is in 4.2.37 vs 4.2.25, or something (with no guarantee that your ‘.25’ is the same as ‘mine’). Bash 4.3 was released by Gnu 2014-02-26 (4.2 on 2011-02-13). Maybe try building that? Otherwise, you may have a regression bug on your hands. (I just built Bash 4.3 on Mac OS X 10.9.2 while adding this comment — it took a couple of minutes after completing the download — and the AZ-test works cleanly on it.)
Bash Bad Substitution Syntax Error: Simple and Quick Fixes
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.
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/bash OUTPUT=$ echo "$OUTPUT"
When I execute the script I see the following output:
(localhost)$ ./subst.sh ./subst.sh: line 3: $: 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/bash OUTPUT=$(ls -al) echo "$OUTPUT"
(localhost)$ ./subst.sh total 8 drwxr-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:
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: $: 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:
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: $: 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/bash BASE_DIR=/opt/base APP_DIR=app CONF_DIR=conf echo $
The code looks correct, let’s run it!
(localhost)$ ./full_path.sh ./full_path.sh: line 6: $: 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/bash BASE_DIR=/opt/base APP_DIR=app CONF_DIR=conf echo $BASE_DIR/$APP_DIR/$CONF_DIR
If I run the script the output is:
(localhost)$ ./full_path.sh /opt/base/app/conf
Option 2: We will keep the outer $ sign and remove the dollar sign immediately before the BASE_DIR variable:
#!/bin/bash BASE_DIR=/opt/base APP_DIR=app CONF_DIR=conf echo $
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/bash BASE_DIR=/opt/base APP_DIR=app CONF_DIR=conf echo $/$/$
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.
[myuser@localhost ~]$ DAY=monday [myuser@localhost ~]$ echo $ monday [myuser@localhost ~]$ echo $ Monday [myuser@localhost ~]$ echo $ MONDAY
A similar syntax but with , instead of ^ allows to convert strings from uppercase to lowercase:
[myuser@localhost ~]$ DAY=MONDAY [myuser@localhost ~]$ echo $ MONDAY [myuser@localhost ~]$ echo $ mONDAY [myuser@localhost ~]$ echo $ 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 --version GNU 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 $ monday (localhost)$ echo $ -bash: $: bad substitution (localhost)$ echo $ -bash: $: 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
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/bash ARCHIVE_NAME=archive.tar.gz tar cvzf $ . if [ $? -eq 0 ]; then ARCHIVE_SIZE=$'> 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: $: 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
I’m a Software Engineer and Programming Coach. I want to help you in your journey to become a Super Developer!