December 13, 2019
About 5 minutes
Technology Cross-platform Shell Environment Variables
Variables in any environment
Using environment variables across platforms and languages
Contents
Environment variables are named values that can be read and acted on by a program but which are defined outside of it, before it runs. They are often used to configure details of a program’s behaviour that may be specific to a system or user, such as setting a default output directory. In build systems, they are often used to keep information such as API keys and certificate passwords private by keeping them out of the code repository. Environment variables exist in some form on virtually every modern platform, but the way you use them varies. To make using them easier, this page provides a quick cross-platform guide to common environment variable tasks.
The basics
This table compares how environment variables are used from different command line shells:
Action | GNU/Linux, BSD, macOS | Windows cmd | PowerShell1 |
---|---|---|---|
Use a value | $NAME | %NAME% | $Env:NAME |
Set a value | export NAME="Value" | set NAME=Value | $Env:NAME="Value" |
Print a value | echo $NAME orprintenv NAME | echo %NAME% orset NAME | $Env:NAME |
List all | printenv | set | ls $Env: |
1 PowerShell is primarily found on Windows, but it is cross-platform.
For example, if the environment variable
TARGET
refers to a target directory, you wouldcd $TARGET
on macOS butcd %TARGET%
on Windows.
Persisting variables
Normally an environment variable does not survive the shell or process that creates it, so you need to re-set any variables you use every session. You can get around this by setting the desired variables automatically whenever you start a terminal.
GNU/Linux, BSD
Edit the script that is run when you log in or start a terminal. The exact steps to do this can depend on several factors (see below), but the following will work most of the time:
- Edit the script that is run for new shells:
nano ~/.bashrc
- Add lines to define the desired variables:
export NAME="Value"
- Save the file and exit the editor:
Ctrl + O, Ctrl + X
To define a variable for all users on the machine,
sudo nano /etc/bash.bashrc
instead.
Troubleshooting
There are many ways for the above to go wrong. First, the instructions assume you have nano
installed. (It’s a common text file editor; you can substitute vi
or emacs
or whatever you have available.) Second, they assume you are using the Bash shell. (You probably are, but you can echo $SHELL
to find out.) Third, Bash actually runs different startup script files depending on how the shell is started. If you are logging in (for example, via ssh
), then Bash will look for ~/.bash_profile
, ~.bash_login
, or ~/.profile
, and run the first one it finds. If you are not logging in (for example, opening a terminal window on your desktop), then it will look for ~/.bashrc
instead. But, most ~/.bash_profile
scripts check for and run ~/.bashrc
if it exists, using ~/.bashrc
usually works regardless. (As a final caveat, if the shell is non-interactive, that is, not tied to a terminal, Bash runs the script specified in the BASH_ENV
environment variable!)
macOS
The basic idea is the same as for other Unix family systems. The file you edit depends on the version, though. (Starting in macOS 10.15, the default shell changed to zsh
.)
Version 10.15+
- Edit the script that is run for new shells:
nano ~/.zshrc
- Add lines to define the desired variables:
export NAME="Value"
- Save the file and exit the editor:
Ctrl + O, Ctrl + X
Older versions
- Edit the script that is run for new shells:
nano ~/.bash_profile
- Add lines to define the desired variables:
export NAME="Value"
- Save the file and exit the editor:
Ctrl + O, Ctrl + X
Why
~/.bash_profile
instead of~/.bashrc
? By default the Terminal app treats new shells as login shells, and the default~/.bash_profile
does not include~/.bashrc
. If you want to use~/.bashrc
for consistency, add the following to~/.bash_profile
:if [ -r ~/.bashrc ]; then
source ~/.bashrc
fi
Windows
Environment variables for the current user (and the entire system) are usually edited from a control panel applet. You can bring it up as follows:
- Press Windows + I.
- In the Find a setting search field, type
env
. - Choose Edit environment variables for your account.
- Use the dialog to add, delete, or edit variables.
You can also open this dialog from the command line:
rundll32 sysdm.cpl,EditEnvironmentVariables
With PowerShell, you can also persist an environment variable from the command line (this relies on the .NET class System.Environment
):
[System.Environment]::SetEnvironmentVariable("NAME", "Value", [System.EnvironmentVariableTarget]::User)
Changing
User
toMachine
would affect the entire system and not just your account, but requires appropriate privileges (for example, by using Run as Administrator to start the shell).
Access from programs
This section lists example snippets to get the value of an environment variable in many popular languages.
Environment variable names are case sensitive on most every platform except Windows. To avoid trouble, always treat them as if they were case sensitive.
C
#include <stdlib.h>
// ...
// NULL if variable is not defined
char* nameEnv = getenv("NAME");
C++
#include <cstdlib>
// ...
// NULL if variable is not defined
char* nameEnv = std::getenv("NAME");
C#
using System;
// ...
// null if variable is not defined
string nameEnv = Environment.GetEnvironmentVariable("NAME");
Java
// System.getenv() returns a Map<String, String> of all env vars
// null if variable is not defined
String nameEnv = System.getenv().get("NAME");
Node.js
// undefined if variable is not defined
let nameEnv = process.env.NAME;
// or
let nameEnv2 = process.env['NAME'];
PHP
// FALSE if variable is not defined
$nameEnv = getenv('NAME');
Python
import os
# ...
# None if variable is not defined
nameEnv = os.environ.get('NAME')
# or
nameEnv = os.getenv('NAME', 'default value')
Common environment variables
There are plenty more; these are some of the most useful in practice.
GNU/Linux, BSD, macOS
Name | Purpose |
---|---|
PATH | Colon-separated list of directories to search for shell commands. |
USER | Your current username (e.g., jane ). |
HOME | Path of your home directory (e.g., /home/jane ). |
PWD | Path of the current working directory. |
SHELL | Path to the shell you are using (e.g., /bin/bash ). |
Windows
Name | Purpose |
---|---|
PATH | Semicolon-separated list of directories to search for shell commands. |
PATHEXT | Semicolon-separated list of file extensions (including dot) considered to be executable as commands. |
USERNAME | Your current username. |
USERPROFILE | Path of your home directory (e.g., C:\Users\jane ). |
ProgramFiles | Path of the directory where programs are installed. |
TEMP | Path of the directory to use for temporary files. |
AppData | Path of the directory where program settings and other per-user data should be stored, if that data should “roam” with the user to other machines. |
LocalAppData | Path of the directory where per-user data that should not roam to other machines should be stored. (For example, very large files or files only valid for this machine.) |
Have a comment or correction? Let me know! I don’t use an automated comment system on this site, but I do appreciate feedback and I update pages accordingly.