bash: ${...}: bad substitution
verified onenvironmentlocal · linux 6.18.44-fc-v139 x64 · GNU bash 5.2.21updated
- tool
- Bash
- exit code
- 1
- versions
- bash 4.x, bash 5.x
- os
- linux, macos, windows
bad substitution means the shell could not parse a ${...} expansion. Two causes cover most cases: the expansion text is invalid (${name bad}), or a bash-only expansion such as ${name^^} runs in a POSIX shell like dash. Check how the script is started (sh or bash) and read the expansion against the bash manual.
Reproduce it
bash -c 'echo ${name bad}'Output · exit 1
bash: line 1: ${name bad}: bad substitutionArithmetic goes in $(( )), not in ${ }:
bash -c 'n=1; echo $((n + 1))'Output
2
It works in bash but not with sh
On Debian and Ubuntu sh is dash, so sh script.sh ignores the shebang and rejects bash-only syntax.
sh -c 'name=hello; echo ${name^^}'
# sh: 1: Bad substitution
bash -c 'name=hello; echo ${name^^}'
# HELLOCheck which shell sh is with ls -l /bin/sh. In CI and Dockerfiles RUN and run: steps may also use sh; select bash explicitly (shell: bash in GitHub Actions).
Sources
Related pages
errors · bashbash: NAME: unbound variablebash: unbound variable appears under set -u when a script reads a variable that was never set, often $1 or an env var. Use ${VAR:-default} or check it first.errors · bashbash: syntax error near unexpected tokenbash prints this when its parser meets an unexpected word: a missing then, do or semicolon, unquoted parentheses, or CRLF line endings. Causes and fixes.flags · bashset -euo pipefail: what each flag does in bashset -e exits on the first failing command, -u treats unset variables as errors and -o pipefail makes a pipeline fail if any command in it fails. Examples.