Bash variables are more like named pointers to strings than strict typed containers.

Let’s see it in action. Imagine you have a script that needs to process a list of files.

#!/bin/bash

# Define a variable with a list of files
FILES="report.txt data.csv config.json"

# Loop through the files and print their names
for FILE in $FILES; do
  echo "Processing: $FILE"
done

# Define another variable, this time with a number
COUNT=10

# Perform a simple arithmetic operation
echo "The count is: $COUNT"
echo "Adding 5 to the count: $((COUNT + 5))"

# Bash treats numbers as strings by default, but can perform arithmetic
# when explicitly told to with $((...)) or 'expr'.

When you run this script, you’ll see:

Processing: report.txt
Processing: data.csv
Processing: config.json
The count is: 10
Adding 5 to the count: 15

The core problem Bash variables solve is state management within scripts. You need to store values – whether they’re strings, numbers, or lists – and retrieve them later. Bash’s approach is remarkably flexible, and sometimes, surprisingly rigid.

Internally, when you assign FILES="report.txt data.csv config.json", Bash creates a symbol table entry for FILES and associates it with the literal string "report.txt data.csv config.json". When you use $FILES in a context like for FILE in $FILES, Bash performs a process called "word splitting" on the value of FILES using delimiters defined by the IFS (Internal Field Separator) variable (which defaults to space, tab, and newline). This breaks the string into individual "words" that the for loop can iterate over.

For arithmetic, COUNT=10 stores the string "10". The expression $((COUNT + 5)) tells Bash to interpret the value of COUNT as an integer and perform addition. Without the $((...)), echo "Adding 5: $COUNT + 5" would simply output Adding 5: 10 + 5.

The most surprising truth is that Bash doesn’t have true "integers" or "floats" in the way most programming languages do. Every variable is fundamentally a string. When you perform arithmetic operations like $((...)), Bash performs a type coercion on the fly, treating the string as an integer. This can lead to subtle bugs if you’re not careful. For instance, echo $((010 + 1)) will result in 9 because Bash interprets 010 as an octal number. If you intended it to be decimal, you’d need to ensure it’s represented as 10.

The next concept you’ll grapple with is how to handle strings containing spaces or special characters, and the various quoting mechanisms Bash offers to control word splitting and expansion.

Want structured learning?

Take the full Bash course →