# Variables and the Environment — Bash / Shell Scripting

Source: https://www.skillbyai.com/en/bash/v-vars

> Assign, export and scope variables correctly.

## Strings by default

Assign a variable with `name=value`, **with no spaces around `=`**: `count = 3` tries to run a command named `count`. Read it with `$name` or `${name}`. Bash variables are **strings** by default; arithmetic happens only in arithmetic contexts. Names are case-sensitive; by convention, use lowercase for script-local variables and UPPERCASE for **environment variables** and constants, to avoid clobbering system variables such as `PATH`, `HOME` or `USER`. A plain variable is visible only in the current shell; **`export name`** puts it in the environment so **child processes** (commands you run) inherit it. Setting a variable just for one command is possible with a prefix: `LANG=C sort file`. `readonly` makes a variable constant; `local` (inside functions) limits its scope; `unset` removes it. Special variables include `$0` (script name), `$1`…`$9` (arguments), `$#` (argument count), `$?` (last status), `$$` (shell PID) and `$!` (last background PID).

## Shell variables and the environment

Exported variables are copied into each child process's environment; plain ones stay in the shell.

![A parent box holding several labelled slots, some highlighted; arrows copy only the highlighted slots into two child boxes below.](assets/figures/bash/section-2-map.svg) — Figure 2.1 — Exported variables are inherited by child processes.

## Assignment, export and per-command variables

Only exported variables reach child processes.

```bash
greeting="hello"            # no spaces around =
readonly MAX_RETRIES=3

bash -c 'echo "child sees: [$greeting]"'   # empty: not exported

export API_URL="https://api.example.com"
bash -c 'echo "child sees: $API_URL"'     # inherited

TZ=Asia/Kolkata date          # variable set only for this one command

echo "script: $0, args: $#, pid: $$"
```

## Never name a variable PATH

A loop such as `for PATH in ...` silently overwrites the command search path, after which every external command fails with "command not found". Lowercase names for your own variables avoid this class of bug.

**Quiz:** Which assignment is valid Bash?

- [ ] count = 3
- [ ] $count=3
- [x] count=3
- [ ] let count := 3

*Answer:* count=3. Bash assignments must not have spaces around the equals sign.
