238
#!/bin/bash

jobname="job_201312161447_0003"
jobname_pre=${jobname:0:16}
jobname_post=${jobname:17}

This bash script gives me Bad substitution error on ubuntu. Any help will be highly appreciated.

Arindam Choudhury
  • 2,816
  • 2
  • 18
  • 22

14 Answers14

296

The default shell (/bin/sh) under Ubuntu points to dash, not bash.

me@pc:~$ readlink -f $(which sh)
/bin/dash

So if you chmod +x your_script_file.sh and then run it with ./your_script_file.sh, or if you run it with bash your_script_file.sh, it should work fine.

Running it with sh your_script_file.sh will not work because the hashbang line will be ignored and the script will be interpreted by dash, which does not support that string substitution syntax.

Vanni Totaro
  • 5,211
  • 2
  • 28
  • 42
  • 14
    @DanFromGermany because that's the only reason for that error, i.e. he's running the script in a way that doesn't consider the hashbang, and that bash syntax is not supported by some other shell (probably dash). Questions don't always contain all the needed details, and we must join the dots... anyway feel free to downvote my answer. – Vanni Totaro Dec 01 '15 at 11:10
  • 3
    I dont need to downvote. I have the same error message `bad substitution` and I'm just trying to gather information but this question doesn't help because it has too few information. – Daniel W. Dec 01 '15 at 12:47
  • 4
    @DanFromGermany you could try posting your own question, maybe it's not exactly the same problem. – Vanni Totaro Dec 01 '15 at 13:27
  • 1
    and I was using `zsh` :facepalm: – asgs Feb 03 '21 at 15:45
  • 2
    Thanks for this! I just got bit by this too. Just what we needed: another shell program with subtle quirks that make it fit on a 5.25 inch disk. – Greg Graham Aug 03 '22 at 20:13
117

I had the same problem. Make sure your script didnt have

#!/bin/sh 

at the top of your script. Instead, you should add

#!/bin/bash
ZeMoon
  • 20,054
  • 5
  • 57
  • 98
Guest
  • 1,179
  • 1
  • 7
  • 2
  • 16
    I used `#!bin/bash` and `sh script.sh`, it still gave me the error message. Then `./script.sh` works. – whyisyoung Apr 09 '15 at 02:13
  • 1
    If your file is missing a shebang at the top adding `#!/bin/bash` will also fix the *Bad substitution*. – Jamie Aug 20 '16 at 09:56
  • 1
    @whyisyoung your variable could be having a dot (.) in its name. It gives bad subst. error. – user13107 Sep 07 '16 at 01:13
  • 8
    @whyisyoung the `#!` line is used only when you execute your script directly. If you use `sh script.sh` the line is completely ignored. – bfontaine Oct 04 '18 at 14:21
  • yes, got same issue on Ubuntu because it default using dash to run script. – suhao399 Mar 10 '22 at 10:26
  • This is the correct answer for me, I had a #!/bin/sh at the top of my script (erroneously), under centos doing ./myscript.sh it ignored the shebang, ran it under bash, and it worked. In Ubuntu it ran it (correctly) in /bin/sh and failed. – Giles Apr 21 '22 at 10:17
98

For others that arrive here, this exact message will also appear when using the env variable syntax for commands, for example ${which sh} instead of the correct $(which sh)

Nacho Coloma
  • 7,070
  • 2
  • 40
  • 43
  • 13
    The difference is curly brace `{` vs normal bracket `(` (took me a little time to figure out what you were showing) – A H Apr 01 '21 at 17:04
25

Your script syntax is valid bash and good.

Possible causes for the failure:

  1. Your bash is not really bash but ksh or some other shell which doesn't understand bash's parameter substitution. Because your script looks fine and works with bash. Do ls -l /bin/bash and check it's really bash and not sym-linked to some other shell.

  2. If you do have bash on your system, then you may be executing your script the wrong way like: ksh script.sh or sh script.sh (and your default shell is not bash). Since you have proper shebang, if you have bash ./script.sh or bash ./script.sh should be fine.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • 8
    I'd be surprised if `/bin/bash` (not `/bin/sh`) were ever linked to a different shell. – chepner Dec 16 '13 at 17:46
  • ksh is actually where most of bash's syntax extensions originated from; it *certainly* has the specific parameter expansion syntax in question. I wouldn't tend to suggest calling it out as a shell unlikely to be capable. – Charles Duffy Apr 28 '17 at 23:13
10

Try running the script explicitly using bash command rather than just executing it as executable.

Ravindra S
  • 6,302
  • 12
  • 70
  • 108
  • 5
    Good one. It would be helpful to add some sample output to make it more clear, by using `sh script` and `bash script`... my suggestion :) – fedorqui Dec 16 '13 at 16:23
8

Also, make sure you don't have an empty string for the first line of your script.

i.e. make sure #!/bin/bash is the very first line of your script.

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
wizurd
  • 3,541
  • 3
  • 33
  • 50
7

Not relevant to your example, but you can also get the Bad substitution error in Bash for any substitution syntax that Bash does not recognize. This could be:

  • Stray whitespace. E.g. bash -c '${x }'
  • A typo. E.g. bash -c '${x;-}'
  • A feature that was added in a later Bash version. E.g. bash -c '${x@Q}' before Bash 4.4.

If you have multiple substitutions in the same expression, Bash may not be very helpful in pinpointing the problematic expression. E.g.:

$ bash -c '"${x } multiline string
$y"'
bash: line 1: ${x } multiline string
$y: bad substitution
Daniel Darabos
  • 26,991
  • 10
  • 102
  • 114
  • 4
    This is the first hit for `Bad substitution` so I thought I'd include the case that we ran into. (It was `@Q` in Bash 4.3 hiding in a long multi-line expression.) – Daniel Darabos Apr 06 '20 at 15:48
  • 4
    This was my issue when running Bash 3.x on mac – jrnxf May 20 '20 at 17:39
  • 2
    [Prooflink](https://github.com/bminor/bash/blob/bash-4.4-alpha/CHANGES#L425-L426) regarding `@Q` being added in `bash-4.4`. – x-yuri Jun 12 '20 at 15:37
2

Both - bash or dash - work, but the syntax needs to be:

FILENAME=/my/complex/path/name.ext
NEWNAME=${FILENAME%ext}new
Hagen
  • 21
  • 1
  • 2
    That's a completely different operation. Also, since the OP was following good practices by using lower-case variable names (see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html -- uppercase names are used for variables with meaning to the OS or shell; lowercase names are reserved for application use), it behooves to do likewise. – Charles Duffy Apr 28 '17 at 23:14
2

I was adding a dollar sign twice in an expression with curly braces in bash:

cp -r $PROJECT_NAME ${$PROJECT_NAME}2

instead of

cp -r $PROJECT_NAME ${PROJECT_NAME}2
sashoalm
  • 75,001
  • 122
  • 434
  • 781
0

I have found that this issue is either caused by the marked answer or you have a line or space before the bash declaration

Ahmed Oladele
  • 11
  • 1
  • 2
0

Looks like "+x" causes problems:

root@raspi1:~# cat > /tmp/btest
#!/bin/bash

jobname="job_201312161447_0003"
jobname_pre=${jobname:0:16}
jobname_post=${jobname:17}
root@raspi1:~# chmod +x /tmp/btest
root@raspi1:~# /tmp/btest
root@raspi1:~# sh -x /tmp/btest
+ jobname=job_201312161447_0003
/tmp/btest: 4: /tmp/btest: Bad substitution
0

in my case (under ubuntu 18.04), I have mixed $( ${} ) that works fine:

BACKUPED_NB=$(ls ${HOST_BACKUP_DIR}*${CONTAINER_NAME}.backup.sql.gz | wc --lines)

full example here.

Neuron
  • 5,141
  • 5
  • 38
  • 59
bcag2
  • 1,988
  • 1
  • 17
  • 31
0

I used #!bin/bash as well tried all approaches like no line before or after #!bin/bash.
Then also tried using +x but still didn't work. Finally i tried running the script ./script.sh it worked fine.

#!/bin/bash
jobname="job_201312161447_0003"
jobname_post=${jobname:17}

root@ip-10-2-250-36:/home/bitnami/python-module/workflow_scripts# sh jaru.sh
jaru.sh: 3: jaru.sh: Bad substitution

root@ip-10-2-250-36:/home/bitnami/python-module/workflow_scripts# ./jaru.sh
root@ip-10-2-250-36:/home/bitnami/python-module/workflow_scripts#

prashant thakre
  • 5,061
  • 3
  • 26
  • 39
0

In my case I eventually found I had a missing } for one of the environmental variables. ${model.a should have been ${model}.a

The takeaway is that it may be a typo.

I am editing in vi on SCO 5.0.5 so please don't bash me for missing a syntax error.

spemble
  • 2,788
  • 2
  • 16
  • 12