Bash increment variable: add 1, counters, loops, and `(( ))` vs `$(( ))`

You bump a counter for every line processed, for every host in a list, or for every retry. In Bash that almost always means integer arithmetic in $(( … )) or (( … )), or a for (( … )) header that advances the index for you. The patterns below stay readable; pay extra attention to post- vs pre-increment when you reuse the expression’s value in another assignment.

Tested all the commands and code from this article on Ubuntu 25.04, kernel 6.14.0-37-generic, Bash 5.2.37.

For comparisons inside loops, keep bash compare numbers nearby.


Bash add 1 to variable (the usual patterns)

Plain arithmetic expansion: var=$((var + 1))

Works everywhere you need a new value; no side effects beyond assignment:

bash
x=5
x=$((x + 1))
echo "$x"

Output:

output
6

Arithmetic command: ((var++)) and ((++var))

(( … )) evaluates like the inside of a C expression. var++ returns the old value then increments; ++var increments then returns the new value.

Standalone (you only care about the final x):

bash
i=0
((i++))
echo "after post-increment alone: $i"

Output:

output
after post-increment alone: 1

When you capture the expression, the difference matters:

bash
i=0
j=$((i++))
echo "j=$j i=$i"

i=0
j=$((++i))
echo "j=$j i=$i"

Output:

output
j=0 i=1
j=1 i=1

Compound assignment inside (( ))

bash
x=5
((x += 2))
echo "$x"

Output:

output
7

let (older style, still valid)

bash
let x=1
let x+=2
echo "$x"

Output:

output
3

expr (external, POSIX—avoid for hot loops)

bash
y=1
y=$(expr "$y" + 1)
echo "$y"

Output:

output
2

Bash increment variable in loop

C-style for (( … ))

The third clause of for ((i=0; i<n; i++)) is the classic bash increment variable in loop form (see the full bash for loop write-up):

bash
for ((i = 0; i <= 3; i++)); do
  echo "i=$i"
done

Output:

output
i=0
i=1
i=2
i=3

Separate counter over a word list

When you iterate words but still need an index:

bash
n=0
for name in a b c; do
  echo "$n: $name"
  ((n++))
done
echo "final count: $n"

Output:

output
0: a
1: b
2: c
final count: 3

Bash increment counter with while

Same arithmetic; often paired with read or a condition (see bash while loop):

bash
count=0
while [[ $count -lt 3 ]]; do
  echo "count=$count"
  ((count++))
done

Output:

output
count=0
count=1
count=2

Integer-only arithmetic

(( … )) and $(( … )) treat variables as integers. Strings that are not valid integers cause errors—normalize input first or stay in string land.

Declare integers when it helps clarity (optional):

bash
declare -i hits=0
((hits++))
echo "$hits"

Output:

output
1

Pitfalls worth remembering

  • set -u: incrementing an unset variable is an error—initialize n=0 before ((n++)).
  • set -e: ((x++)) returns exit status 1 when the expression’s value is 0 (post-increment still “returns” the old value). Starting from x=0, a bare ((x++)) can therefore stop the script. Safer under set -e: ((++x)), ((x+=1)), or x=$((x+1)).
  • Post vs pre inside assignments ($((i++)) vs $((++i)))—easy to get off-by-one when you also use the return value.
  • Floating point: use bc or awk command; ((x += 0.1)) is not the Bash integer model.

Quick reference (pick one style per script)

Style Example Typical use
Expansion assign x=$((x+1)) clearest “add n”
(( post ((x++)) bump inside loops
(( pre ((++x)) need new value in same expression
(( add n ((x+=5)) step sizes other than 1
let let x+=1 legacy scripts
expr x=$(expr "$x" + 1) portability without Bash

Summary

Incrementing in Bash is integer work: x=$((x+1)) is the clearest “add one,” ((x++)) or ((++x)) match C habits (watch post- vs pre-increment when you reuse the expression’s value), and the third clause of for ((…; …; i++)) is the usual loop counter form. while and until counters follow the same arithmetic rules. Stick to one style per script, initialize variables before set -u, and reserve expr for rare portability needs—(( )) keeps counter code short and fast.

Further reading:

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)