Scope in Bash

When you open a terminal window, you are starting a program called a shell (usually Bash).
This shell is a running process that reads your commands and executes them.

Any variables you create (for example x=1) are stored in the memory of that specific shell process.
They exist only inside that running shell unless you explicitly make them available elsewhere.

This idea — where a variable exists and where it can be accessed — is called scope.

In Bash, scope is determined by process boundaries. A variable is visible:

  • Inside the shell where it was created
  • Inside functions in that shell (unless restricted with local)
  • Inside child processes only if it has been exported

If a new process is started (for example when you run a script normally), that new process does not automatically inherit all variables from the parent shell. Only exported variables are passed to child processes.

Understanding scope is important because many beginner errors occur when a variable appears to “disappear”. In most cases, the variable still exists — but not in the process you are currently working in.


Shell variables vs environment variables

When you assign a variable:

x=1

This creates a shell variable. It exists only inside the current shell process. If you check it:

echo $x

you will see:

1

However, this variable is not automatically visible to child processes.


Running a script

Suppose you create a script called myscript.sh. Do this by typing nano to open a text editor and copy in the following code:

#!/bin/bash
echo $x

If you run:

./myscript.sh

the script runs in a subshell (child process). If x was defined only as x=1 outwith the subshell then the script will not see it.

To make it visible to child processes, you must export it:

export x=1

Now x becomes an environment variable, and any subprocess started from that shell can access it.


Subshells

Subshells are created explicitly using parentheses:

x=1

( x=2 )

echo $x

This prints 1, not 2.

The parentheses create a new process. Changes inside it do not affect the parent shell.


Functions and local variables

Inside Bash functions, variables are global by default unless declared local.

myfunc() {
  local x=5
  echo $x
}

myfunc
echo $x

The first echo prints 5. The second prints nothing (or the previous value of x if it existed). Using local is the correct way to restrict variable scope inside functions.

Best Practice:

  • Avoid using export unless a variable must be visible to child processes.
  • Define variables inside scripts rather than relying on global shell state.
  • Use local inside functions to avoid unintended side effects.
  • Remember: scripts run as separate processes unless sourced.

Sourcing a script

If instead of running a script you use:

source myscript.sh

or

. myscript.sh

then the script runs in the current shell, and any variables it sets will remain available afterward.

Move on to Making scripts executable, or back to Linux 101


... ...