Bash & Shell Scripting DISCUSSION

Shell script works with bash but fails under sh with a syntax error: what is different?

Started by ruchi sh vs bashdash shellbashismsPOSIX shellshebang line
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Shell script works with bash but fails under sh with a syntax error: what is different?

#1

A deployment script runs fine as ./deploy.sh on my Ubuntu machine, but on the target it is started with sh deploy.sh and stops with Syntax error: "(" unexpected at the line targets=(web db cache). After I rewrote that line, the next failure was [[: not found.

I thought sh and bash were the same shell. What is the actual difference, and how should I write the script so it works in both places?

Community replies 5

Re: Shell script works with bash but fails under sh with a syntax error: what is different?

#2

sh is not a particular program; it is whatever POSIX-compatible shell the system installs at /bin/sh. On Debian and Ubuntu that is dash, on Alpine and most embedded Linux systems it is BusyBox ash, and on some distributions it is Bash itself running in POSIX mode. Bash is a much larger shell with many extensions beyond the POSIX standard.

The #! line is only consulted when the file is executed directly. ./deploy.sh uses the interpreter named there, but sh deploy.sh ignores it and hands the file to sh. Run it as bash deploy.sh or make it executable and call it by path.

Re: Shell script works with bash but fails under sh with a syntax error: what is different?

#3

The features that most often break under a plain sh, with their portable replacements:

  • arrays such as a=(x y z): not available; loop over a list of words or use the positional parameters with set -- x y z
  • [[ ... ]]: use [ ... ] with quoted variables, and = instead of ==
  • function name {: write name() {
  • source file: use . file
  • {1..10}, ${var//a/b}, ${var,,}, <<< and <(...): use seq, sed, tr, here-documents and pipes

$(...), $((...)), ${var:-default}, ${var#prefix} and ${var%suffix} are all POSIX and safe to use.

Re: Shell script works with bash but fails under sh with a syntax error: what is different?

#4

echo is a quieter difference. In Bash, echo -e "a\tb" prints a tab between the letters. In dash, echo always interprets backslash escapes and does not know -e, so it prints the text -e in front. For anything beyond a plain fixed string use printf, which behaves the same everywhere: printf '%s\n' "$value" or printf 'Total: %d files\n' "$n".

Redirections differ too: &> file is Bash only, and in a POSIX shell it is parsed as a background command followed by a redirection. Use > file 2>&1.

Re: Shell script works with bash but fails under sh with a syntax error: what is different?

#5

Choose deliberately rather than aiming for both by accident. If Bash is installed wherever the script runs, start it with #!/bin/bash (or #!/usr/bin/env bash when its location varies), invoke it as a program, and use arrays and [[ ]] freely. If it has to run on minimal systems such as BusyBox-based firmware or small container images where Bash is absent, write POSIX sh from the start and declare #!/bin/sh.

Bash versions matter as well: associative arrays (declare -A) and mapfile need Bash 4, and macOS still ships Bash 3.2 as /bin/bash.

Re: Shell script works with bash but fails under sh with a syntax error: what is different?

#6

To find problems before the target does, test with the strictest shell you have: dash -n deploy.sh does a syntax-only check and dash deploy.sh runs it. The shellcheck linter reads the #! line and warns about constructs that the declared shell does not support, and checkbashisms from the Debian devscripts package does a similar job for #!/bin/sh scripts. Running one of these in your build pipeline keeps Bash-only syntax from creeping back in.

TEP COMMUNITY