Use `(( ... ))` instead of `let ...` for arithmetic

`let expr` is an older, quoting-sensitive arithmetic form. SC2219 recommends the clearer `(( expr ))` compound command.

Problem

`let` performs arithmetic evaluation, but each argument to `let` is subject to word splitting unless quoted, so expressions with spaces, `*`, or other shell metacharacters need careful quoting to avoid being mangled or triggering pathname expansion — e.g. `let x = 1 + 2` fails without quotes around the whole expression. `(( ... ))` is a Bash/Ksh compound command dedicated to arithmetic evaluation that does not undergo word splitting or globbing on its contents, making it both safer and easier to read, so ShellCheck suggests it as the preferred modern equivalent.

Bad

let count = count + 1
let "total = a * b"

Good

(( count = count + 1 ))
(( total = a * b ))
# or the increment shorthand:
(( count++ ))

Explanation

`(( ... ))` evaluates its entire contents as a single C-like arithmetic expression without shell word splitting, so operators, spaces, and variable names behave predictably without extra quoting. It also sets the exit status based on whether the resulting value is zero, which is useful directly in conditionals.

Related

SC2004

SC2003

SC1102

When It Matters

let takes its arguments as strings and evaluates them, which means quoting and word splitting apply before the arithmetic does — so let "x = $y + 1" behaves differently depending on what is in y, and an expression containing a space must be quoted or it becomes several separate expressions. (( )) parses arithmetic directly, so spaces are free, and the code reads like arithmetic in any other language.

Second Example

Note

Both let and (( )) return exit status 1 when the expression evaluates to zero, so under set -e prefer (( count++ )) || true, or use the pre-increment form.

Exceptions

let is not wrong, just harder to quote correctly, and it is equally non-POSIX. In a POSIX sh script use the arithmetic expansion form instead: count=$((count + 1)).

Faq

Q

Why does (( x++ )) abort my script under set -e?

A

Because the expression evaluates to the value before incrementing, and zero means exit status 1. Use (( ++x )) or append || true.

Q

Is (( )) available in sh?

A

No. Use x=$((x + 1)) or the : $((...)) idiom in POSIX sh.

Q

Does arithmetic support floating point?

A

No, Bash arithmetic is integer only. Use awk or bc for decimals.