Skip to content
Laviyx Learn

Try

Linux and Bash course menu

Bash Variables and Quoting Explained

Create Bash variables, understand single and double quotes, avoid word-splitting bugs, do arithmetic with $(( )), use default values, and read command output into variables.

Intermediate6 min readUpdated
On this page

Variables#

Assign with = and no spaces, and read with $:

Terminal
name="Asha"
age=24
echo "$name is $age"
Output
Asha is 24

Use ${name} when text follows immediately:

Terminal
file="report"
echo "${file}_2026.txt"
echo "$file_2026.txt"
Output
report_2026.txt
.txt

The second line looks for a variable called file_2026, which is empty.

Bash variables have no types. Everything is text, unless used in arithmetic. Uppercase names are usually for environment variables, and lowercase for your own.

Single and double quotes#

QuotesVariables expanded?Use for
"double"YesAlmost everything
'single'No, text is literalExact text, awk and sed programs
NoneYes, and split into wordsRarely what you want
Terminal
city="New Delhi"
echo "I live in $city"
echo 'I live in $city'
Output
I live in New Delhi
I live in $city

Why quoting matters#

Without quotes, Bash splits a value on spaces, and it expands wildcards. This is the source of many script bugs:

Terminal
file="my report.txt"
touch "$file"
ls -l $file 2>&1 | head -n 2
echo ---
ls -l "$file" | awk '{print $NF}'
Output
ls: cannot access 'my': No such file or directory
ls: cannot access 'report.txt': No such file or directory
---
report.txt

Unquoted, ls received two names: my and report.txt.

Command substitution#

$(...) stores a command's output:

Terminal
count=$(ls -A | wc -l)
today=$(date +%Y)
echo "Year $today, and $count items here"
Output
Year 2026, and 4 items here

Arithmetic#

$(( )) does whole-number arithmetic. Variables do not need $ inside it:

Terminal
a=17
b=5
echo "$((a + b)) $((a * b)) $((a / b)) $((a % b))"
count=1
((count++))
echo "$count"
Output
22 85 3 2
2

Division drops the remainder. For decimals, use awk or bc:

Terminal
awk 'BEGIN {printf "%.2f\n", 17 / 5}'
Output
3.40

Default values#

These expansions handle missing values:

FormMeaning
${name:-text}Use text if name is empty
${name:=text}Also assign it
${name:?message}Stop with an error if empty
${#name}Length of the value
Terminal
echo "Port: ${PORT:-8080}"
PORT=3000
echo "Port: ${PORT:-8080}"
echo "${#PORT} digits"
Output
Port: 8080
Port: 3000
4 digits

This is the normal way to give a script's settings a default.

Special variables#

VariableMeaning
$0The script's name
$1, $2Arguments
$#Number of arguments
$?Exit code of the last command
$$PID of this shell
$!PID of the last background job

Read-only values#

Terminal
readonly VERSION="1.0"
VERSION="2.0"
echo "$VERSION"
Output
bash: VERSION: readonly variable
1.0

Common mistakes#

Practice#

Practice exercise

Given price=250 and qty=3, print Total: 750 using arithmetic, then print the value of DISCOUNT, using 0 if it is not set.

Show solution
Terminal
price=250
qty=3
echo "Total: $((price * qty))"
echo "Discount: ${DISCOUNT:-0}"
Output
Total: 750
Discount: 0

Key takeaway#

Next: Conditions with if and case.

Finished this lesson?