The Ultimate Guide to Shell Variables

The Ultimate Guide to Shell Variables

Everything you need to know about shell variables, including their types, how to create them, and how to export them.

Play this article

Introduction

Before we even talk about shell variables, let us first of all talk about generally what a variable is, because it is one of the things that is popular amongst all programming languages as well as the shell in general.

A variable is a location in the memory of the computer that is being named, that can be used to store data. This is done by declaring a variable name and giving the variable name a value.

So we can now say that shell variables are variables that are used in the shell to store data, which can be accessed by the shell.

Types of Shell Variables

There are about three types of variables in the shell, they are:

  1. Global Variables (Environment Variables)

  2. Local Variables

  3. Variables by Content

Global Variables/Environment Variables

These are variables that are available in all shells. That is you can find them at any location of the shell you are working on irrespective of whether it is a shell or a sub-shell. The env or printenv command can be used to display environment variables.

Below is the environment variable of my Ubuntu as of the point of writing this article.

bene@bene-Nitro-AN515-57:~$ env

SHELL=/bin/bash SESSION_MANAGER=local/bene-Nitro-AN515-57:@/tmp/.ICE-unix/2695,unix/bene-Nitro-AN515-57:/tmp/.ICE-unix/2695 QT_ACCESSIBILITY=1 COLORTERM=truecolor XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg SSH_AGENT_LAUNCHER=openssh XDG_MENU_PREFIX=gnome- GNOME_DESKTOP_SESSION_ID=this-is-deprecated GNOME_SHELL_SESSION_MODE=ubuntu SSH_AUTH_SOCK=/run/user/1000/keyring/ssh XMODIFIERS=@im=ibus DESKTOP_SESSION=ubuntu GTK_MODULES=gail:atk-bridge PWD=/home/bene LOGNAME=bene XDG_SESSION_DESKTOP=ubuntu XDG_SESSION_TYPE=x11 GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1 SYSTEMD_EXEC_PID=2721 XAUTHORITY=/run/user/1000/gdm/Xauthority WINDOWPATH=2 HOME=/home/bene USERNAME=bene LANG=en_US.UTF-8 LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.avif=01;35:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:~=00;90:#=00;90:.bak=00;90:.old=00;90:.orig=00;90:.part=00;90:.rej=00;90:.swp=00;90:.tmp=00;90:.dpkg-dist=00;90:.dpkg-old=00;90:.ucf-dist=00;90:.ucf-new=00;90:.ucf-old=00;90:.rpmnew=00;90:.rpmorig=00;90:.rpmsave=00;90: XDG_CURRENT_DESKTOP=ubuntu:GNOME VTE_VERSION=7200 GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/1ab24cb5_a111_4a5a_94f3_0d9f627bfe35 LESSCLOSE=/usr/bin/lesspipe %s %s XDG_SESSION_CLASS=user TERM=xterm-256color LESSOPEN=| /usr/bin/lesspipe %s USER=bene GNOME_TERMINAL_SERVICE=:1.122 DISPLAY=:1 SHLVL=1 QT_IM_MODULE=ibus XDG_RUNTIME_DIR=/run/user/1000 DEBUGINFOD_URLS=https://debuginfod.ubuntu.com XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/home/bene/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin GDMSESSION=ubuntu DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus _=/usr/bin/env

bene@bene-Nitro-AN515-57:~$

Local Variables

These are variables that are only available in the current shell. They are not available once you move to the sub-shell of your present shell.

For the local variables, you can use the set command, the only thing is that when used without any option, it lists also the environment variables and functions.

So to get only the variables that exist in the local scope only, we can make use of this command: set | grep -v '^BASH_' command. Which will give us only the list of the local variables. This is what is been displayed on my bash shell after running this command.

BASH=/usr/bin/bash BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:globskipdots:histappend:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath COLORTERM=truecolor COLUMNS=95 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus DEBUGINFOD_URLS='https://debuginfod.ubuntu.com ' DESKTOP_SESSION=ubuntu DIRSTACK=() DISPLAY=:1 EUID=1000 GDMSESSION=ubuntu GNOME_DESKTOP_SESSION_ID=this-is-deprecated GNOME_SHELL_SESSION_MODE=ubuntu GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/1ab24cb5_a111_4a5a_94f3_0d9f627bfe35 GNOME_TERMINAL_SERVICE=:1.122 GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1 GROUPS=() GTK_MODULES=gail:atk-bridge HISTCONTROL=ignoreboth HISTFILE=/home/bene/.bash_history HISTFILESIZE=2000 HISTSIZE=1000 HOME=/home/bene HOSTNAME=bene-Nitro-AN515-57 HOSTTYPE=x86_64 IFS=$' \t\n' LANG=en_US.UTF-8 LESSCLOSE='/usr/bin/lesspipe %s %s' LESSOPEN='| /usr/bin/lesspipe %s' LINES=24 LOGNAME=bene LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.avif=01;35:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.webp=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:~=00;90:#=00;90:.bak=00;90:.old=00;90:.orig=00;90:.part=00;90:.rej=00;90:.swp=00;90:.tmp=00;90:.dpkg-dist=00;90:.dpkg-old=00;90:.ucf-dist=00;90:.ucf-new=00;90:.ucf-old=00;90:.rpmnew=00;90:.rpmorig=00;90:.rpmsave=00;90:' MACHTYPE=x86_64-pc-linux-gnu MAILCHECK=60 OLDPWD=/home/bene OPTERR=1 OPTIND=1 OSTYPE=linux-gnu PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin PIPESTATUS=([0]="0") PPID=6047 PS1='[\e]0;\u@\h: \w\a]${debian_chroot:+($debian_chroot)}[\033[01;32m]\u@\h[\033[00m]:[\033[01;34m]\w[\033[00m]$ ' PS2='> ' PS4='+ ' PWD=/home/bene/Desktop QT_ACCESSIBILITY=1 QT_IM_MODULE=ibus SESSION_MANAGER=local/bene-Nitro-AN515-57:@/tmp/.ICE-unix/2695,unix/bene-Nitro-AN515-57:/tmp/.ICE-unix/2695 SHELL=/bin/bash SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor SHLVL=1 SSH_AGENT_LAUNCHER=openssh SSH_AUTH_SOCK=/run/user/1000/keyring/ssh SYSTEMD_EXEC_PID=2721 TERM=xterm-256color UID=1000 USER=bene USERNAME=bene VTE_VERSION=7200 WINDOWPATH=2 XAUTHORITY=/run/user/1000/gdm/Xauthority XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg XDG_CURRENT_DESKTOP=ubuntu:GNOME XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/home/bene/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop XDG_MENU_PREFIX=gnome- XDG_RUNTIME_DIR=/run/user/1000 XDG_SESSION_CLASS=user XDG_SESSION_DESKTOP=ubuntu XDG_SESSION_TYPE=x11 XMODIFIERS=@im=ibus \=Desktop _git_printf_supports_v=yes backupglob='@(##|@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))'

Variables by Content

Apart from categorizing variables based on Global/Environment Variables and Local Variables, we can also categorize them based on the content they hold, on this note, we can have:

  1. String variables

  2. Integer variables

  3. Constant variables

  4. Array variables

You can make some research on this on your own as this is not the focus of this article.

Creating Variables

Variables can also be created on the shell to save a string, integer, constant or array. They are case sensitive, what this means is that declaring a variable NAME is not the same as Name and neither is it the same as name. By default they are capitalized, however, you are free to use a lowercase name as well as have a mixture of letters and digits in the name, although it doesn't accept a variable that is starting with a number. The number can either be in between or at the very end of the variable name.

To set a variable name in the shell, we can simply use:

VARNAME="value"

Notice how there is no space between the VARNAME, the = and also the "value", it is intentional, as any space between them will result in an error.

When assigning values, it is always good to quote strings, for numbers it is not necessary.

Examples

Some examples of how to create variables in the shell.

NAME="Gideon Bature"
YEAR=2023

The first one is how to create a string variable, which can also be a single quotation, and the variable name can also be in lowercase or can only have the first letter capitalized.

While the second one is how to create an integer variable, for this one there is no need for any quotation mark, however, the digits of the integer need to be together, and remember, there shouldn't be any space between the variable name, the = sign and the value of the variable.

Accessing Variables

It is very important to be able to access the variables we have created because every variable is created to be used, hence the need to be able to access those variables.

To access and print a shell variable to the standard output of the shell terminal, you can simply use the command echo followed by a $ sign and then the name of the variable whose value you want to access.

Here is a typical example of that below:

echo $VARNAME

This will print out the value of the variable that is saved in the VARNAME on the shell terminal.

The image below illustrates both how to set a variable and how to access the variable.

You can use this more creatively just like in the image below:

Exporting Variables

Creating a variable in the shell automatically makes that variable to be local, and thus that variable can not be accessed from the sub-shell, it can only be accessed in the current shell where it is been created. Below is an example of what I am saying since I already have two variables I created in the present shell, which are the MYNAME and the YEAR I will enter into the sub-shell of my Bash and will try to access them to see if I can. To go to the sub-shell of your present shell, just use the bash command on your present shell.

From the image above, you could see that when I moved to the sub-shell of my shell, I tried accessing the two variables I created on my main shell, and I wasn't able too, that is to show you that any variable you created is automatically a local variable.

And once I exit the sub-shell back to my shell, I was able to access the variables once again.

Here is where the export comes in. The export command is used to create a global/environment variable. It can also be used to make a local variable to become a global/environment variable.

To use this command to either create a global/environment variable or change a local variable to a global variable, you can simply do this:

export $VARNAME="value"
export VARNAME

The first one is used to create an environment variable and the second one is used to change an already existing local variable to a global/environment variable.

The image below shows an example of how I changed the two variables I created earlier on from a local variable to a global/environment variable.

Conclusion

All these are the knowledge you need to get started with shell variables, as they come in handy when you are dealing with shell scripting and also shell arithmetic which we will be seeing in the next article.

Thank you for reading. You can connect with me on Twitter and LinkedIn.