---
tags:
  - shell
---

# Environmental and shell variables

## Important!

To understand the difference between environmental and shell variables know
that:

- You can spawn child shells from the parent shell that is initiated when you
  first open the terminal. To do this just run `bash` or `zsh` .
- This is a self-contained new instance of the shell. This means:
  - It **will have** access to environmental variables (since they belong to the
    parent / are global)
  - It **will not have** access to any shell variables that are defined in the
    parent.
- **How do you get back to the ‘upper’ parent shell?** Type `exit` .
- Note that:
  - Custom (user-created) shell variables **do not** pass down to spawned shell
    instances, nor do they pass up to the parent
  - Custom (user-created) environment variables do pass down to spawned shell
    instances but do not pass up to the parent. They are lost on `exit` .

Q. What methods are there for keeping track of, preserving, and jumping between
spawned instances? Is this even possible or do they die on `exit` .

## Questions, research

1. If you create a variable manually I guess it won’t make it to any config
   file. How would you create a persistent var that is added to the `.bashrc`
   and thus which would be initialised on every session? Is this where the path
   comes in?
1. What methods are there for keeping track of, preserving, and jumping between
   spawned instances? Is this even possible or do they die on `exit` ?

## What is the shell environment and what are environment variables?

- Every time that you interact with the shell you do so within an
  **environment**. This is the context within which you are working and it
  determines your access to resources and the behaviour that is permitted.

- The environment is an area that the shell builds every time that it starts a
  session. It contains variables that define system properties.

- Every time a [shell session](Shell-sessions-e6dd743dec1d4fe3b1ee672c8f9731f6)
  spawns, a process takes place to gather and compile information that should be
  available to the shell process and its child processes. It obtains the data
  for these settings from a variety of different files and settings on the
  system.

- The environment is represented by strings comprising key-value pairs. For
  example:

  ```bash
  KEY=value1:value2
  KEY="value with spaces":"another value with spaces"
  ```

  As the above shows, a key can have multiple related values. Each one is
  demarcated with a `:` . If the value is longer than a single word, quotation
  marks are used.

- The keys are **variables**. They come in two types: **environmental
  variables** and **shell variables:**

  - Environmental variables are much more permanent and pertain to things like
    the user and his path (the overall session)
  - Shell variables are more changeable for instance the current working
    directory (the current program instance)

Variables can be created via config files that run on the initialisation of the
session or manually created via the command line in the current session

## What are shell variables useful for?

Some deployment mechanisms rely on environmental variables to configure
authentication information. This is useful because it does not require keeping
these in files that may be seen by outside parties.

More generally they are used for when you will need to read or alter the
environment of your system.

## Viewing shell and environmental variables

To view the settings of your current environment you can execute the `env`
command which returns a list of the key-value pairs introduced above. Here are
some of the more intelligible variables that are returned when I run this
command:

```bash
SHELL=/usr/bin/zsh
DESKTOP_SESSION=plasma
HOME=/home/thomas
USER=thomas
PWD=/home/thomas/repos/bash-scripting
PATH=/home/thomas/.nvm/versions/node/v16.8.0/bin:/home/thomas/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/snapd/snap/bin
```

However if you want to target a specific viable you need to invoke `printenv`
with the relevant key, for example:

```bash
printenv SHELL
# SHELL=/usr/bin/zsh
```

Note that `env` and `printenv` do not show all the shell variables, only a
selection. To view all the shell variables along with the environmental
variables use `set` .

## Creating, exporting and deleting variable shell and environment variables

- You set shell variables using the same syntax you would within a script file:

  ```bash
  TEST_SHELL_VAR="This is a test"
  set | grep TEST_SH
  TEST_SHELL_VAR='This is a test'

  # We can also print it with an echo, again exactly as we would with a shell script
  echo S{TEST_SHELL_VAR}
  ```

- We can verify that it is not an environmental variable based on the fact that
  following does not return anything:

  ```bash
  printenv | grep TEST-SH
  ```

- We can verify that this is a shell variable by spawning a new shell and
  calling it. Nothing will be returned from the child shell.

- You can upgrade a shell variable to an environment variable with `export` :

  ```bash
  export TEST_SHELL_VAR
  # And confirm:
  printenv | grep TEST_SH
  TEST_SHELL_VAR='This is a test'
  ```

- We can use the same syntax to create new environment variables from scratch:

  ```bash
  export NEW_ENV_VAR="A new var"
  ```

### Using config files to create variables

You can also add variables to config files that run on login such as your user
`.bashrc` / `.zshrc` . This is obviously best for when you want the variables to
persist and be accessible within every
[shell session](Shell-sessions-e6dd743dec1d4fe3b1ee672c8f9731f6).

## Important environmental and shell variables

### `PATH`

A list of directories that the system will check when looking for commands. When
a user types in a command, the system will check directories in this order for
the executable.

```bash
echo ${PATH}
# /home/thomas/.nvm/versions/node/v16.8.0/bin:/home/thomas/.local/bin:/usr/local/sbin:/usr/local/bin:
# /usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/snapd/snap/bin
```

For example, if you wish to use `npm` commands globally (in any directory) you
will need to have the requisite Node executable in your path, which you can see
above.

### `SHELL`

This describes the shell that will be interpreting any commands you type in. In
most cases, this will be bash by default, but other values can be set if you
prefer other options.

```bash
echo ${SHELL}
# /usr/bin/zsh
```

### `USER`

The current logged in user.

```bash
echo ${USER}
# thomas
```

### `PWD`

The current working directory.

```bash
echo ${PWD}
# /home/thomas
```
