Skip to content

Instantly share code, notes, and snippets.

@CMCDragonkai
Last active February 8, 2025 17:37
Show Gist options
  • Save CMCDragonkai/0a66ba5e37c5d1746d8bc814b37d6e1d to your computer and use it in GitHub Desktop.
Save CMCDragonkai/0a66ba5e37c5d1746d8bc814b37d6e1d to your computer and use it in GitHub Desktop.
Bash: The Scoping Rules of Bash

The Scoping Rules of Bash

There are 5 types of scopes in Bash:

  • Environment Scope - export x=1; echo "$x"; command
  • Shell Scope - x=1; echo "$x"
  • Function Scope - f () { local x=1; echo "$x"; }; f
  • Command Scope - x=1 command
  • Subshell Scope - x=1; (echo "$x"; y=2); echo $y

There is no block scoping for command groups, i.e. { local x=1; } does not work. For the purposes of scoping, comand groups over no isolation. Everything is as if done in the main shell scope.

The environment scope makes variables available in:

  • the current shell,
  • immediate subprocesses,
  • and subshells

The shell scope makes variables available in:

  • the current shell,
  • and subshells

The function scope makes variables available in:

  • the current shell function

The command scope makes variables available in:

  • the immediate command subprocess and nothing else

The subshell scope is the equivalent of a new shell, and has all the features of a shell scope, and its own environment scope. The key feature is that variables declared here will not leak into the parent shell.

If you export a variable inside a function, whether local or not, it will be equivalent to a variable in the main shell's environment scope.

Because there's no block scoping, neither for nor while creates a block scope either. However if you pipe into a while command, you'll create a subshell scope. This is not true for ZSH however.

Both command substitution $() and process substitution <() creates a subshell scope. Note that ZSH has =() while probably creates a subshell scope too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment