Shell builtins · bash builtin
export
Mark shell variables (or bash functions) to be passed to every program the shell starts.
export [-fn] [NAME[=VALUE] ...] or export -p
A shell variable exists only inside the shell that set it. export NAME puts it into the
environment, the list of NAME=value strings that is copied into every child process:
programs, scripts and subshells started from then on. That is how PATH, HOME, EDITOR or
an API_TOKEN reach the programs that read them.
The copy goes one way, downward. A child can change its copy, but nothing it does reaches
the parent, which is why a script cannot set a variable in your terminal (unless you
source it). And export affects children started after it; a program already running
keeps the environment it was born with.
To give a variable to one command only, skip export and prefix the command:
LANG=C sort file. To remove a variable from the environment but keep it in the shell, use
export -n; to remove it entirely, unset. export -p (or plain export) lists what is
exported.
Examples
Make a variable visible to child processes
COLOR=blue
bash -c 'echo "child sees COLOR=[$COLOR]"'
export COLOR
bash -c 'echo "child sees COLOR=[$COLOR]"'
child sees COLOR=[] child sees COLOR=[blue]
Before export, COLOR is a plain shell variable and the child bash gets nothing. After
it, the variable is part of the environment of every command started later.
Set and export in one step
export API_URL=http://localhost:8080 RETRIES=3
env | grep -E '^(API_URL|RETRIES)='
API_URL=http://localhost:8080 RETRIES=3
export NAME=value assigns and exports at once, for as many names as you list. env,
being a separate program, shows what children receive.
Set a variable for a single command
TZ=Asia/Tokyo date +%H:%M-%Z
date +%H:%M-%Z
echo "TZ in this shell: [${TZ-unset}]"
05:19-JST 20:19-UTC TZ in this shell: [UTC]
A NAME=value prefix puts the variable in that one command's environment only. date
reads TZ from its environment; afterward the shell still has its own value (UTC in
this sandbox), untouched.
A child cannot change the parent's variable
export STAGE=dev
bash -c 'STAGE=prod; echo "child changed it to $STAGE"'
echo "parent still has $STAGE"
child changed it to prod parent still has dev
The child receives a copy of the environment. Its assignment changes only that copy, so
the parent's value is untouched. Pass results back through output instead:
STAGE=$(cmd).
List exported variables
export -p | grep -E 'HOME|EDITOR|LANG'
declare -x EDITOR="vi" declare -x HOME="/home/dev" declare -x LANG="C.UTF-8"
export -p prints each exported variable as a declare -x command that could recreate
it. Variables the shell inherited, such as HOME and LANG, are exported automatically;
EDITOR comes from the environment this sandbox starts with.
Stop exporting a variable with -n
export TOKEN=abc123
export -n TOKEN
echo "shell still has: $TOKEN"
bash -c 'echo "child sees: [$TOKEN]"'
shell still has: abc123 child sees: []
export -n removes the export flag but keeps the value in the current shell. Useful for
keeping a secret away from the commands you run next.
Add a directory to PATH
mkdir -p ~/bin
printf '#!/bin/sh\necho "hello from ~/bin"\n' > ~/bin/hello
chmod +x ~/bin/hello
export PATH="$HOME/bin:$PATH"
hello
echo "$PATH" | tr : '\n' | head -n 3
hello from ~/bin /home/dev/bin /usr/local/bin /usr/bin
PATH is already exported, so reassigning it is enough, but writing export makes the
intent clear. Prepending gives your directory priority. In a startup file this line
belongs in ~/.profile or ~/.bashrc.
Export a function to child bash processes with -f
greet() { echo "hello, $1"; }
export -f greet
bash -c 'greet child'
printf '%s\n' a b | xargs -n 1 bash -c 'greet "$1"' _
hello, child hello, a hello, b
export -f passes a function through the environment to child bash processes. This
is how to call a shell function from xargs, find -exec or parallel, which can only
start programs. Each value is passed as $1 (after a placeholder $0) rather than pasted
into the code, so odd file names cannot inject commands. Other shells such as dash will
not see exported functions.
Subshells see unexported variables, programs do not
LOCAL_ONLY=yes
( echo "subshell: $LOCAL_ONLY" )
echo "pipe: $(echo "$LOCAL_ONLY")"
bash -c 'echo "new bash: [$LOCAL_ONLY]"'
subshell: yes pipe: yes new bash: []
( ... ) and $( ... ) are forks of the current shell, so they inherit every variable.
bash -c is a new program and gets only the environment. This difference is why a
variable "works in the script but not in the program it runs".
Common pitfalls
Expecting a script to export a variable into your terminal. Children cannot change their parent;
sourcethe script instead.export VAR=$(cmd)returns the status ofexport, which is 0, so a failingcmdgoes unnoticed byset -eor&&. Assign first, thenexport VAR.Spaces around
=:export NAME = valueexports three names. WriteNAME=valuewith no spaces.Exporting secrets more widely than needed: every program you start afterward can read them, including from
/proc/PID/environ. Prefer a per-command prefix.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
export NAME=valueandexport -pare POSIX.export -nandexport -fare bash-only; in dash they are errors. zsh supportsexportwith the same basic syntax.
Options worth knowing
A selection, described in our own words. For the full list, see bash(1), SHELL BUILTIN COMMANDS.
| Option | What it does |
|---|---|
-p | List all exported variables as reusable declare -x commands. |
-n | Remove the export flag from the named variables, keeping their values. |
-f | Treat the names as shell functions and export those (bash only). |
Related
envPrint the environment, or run a command with a modified environment.printenvPrint all environment variables, or the values of the ones you name.unsetRemove shell variables, array elements or functions, so they no longer exist rather than being empty.declareCreate variables with attributes (array, associative array, integer, read-only, exported), or show how variables are defined.sourceRun the commands in a file inside the current shell, so its variables, functions and directory changes stay in effect.setTurn shell options such as -e, -u, -x and pipefail on or off, and replace the positional parameters.- Environment variablesHow export passes variables to child processes, the one-command NAME=value prefix, loading .env files, and why a child cannot change its parent.
- VariablesAssigning and reading shell variables, the no-spaces rule, braces, unset vs empty, scope, readonly, and the special variables bash sets for you.
- Subshells and command groupingThe difference between ( ... ) and { ...; }, what a subshell inherits and what it cannot change, which constructs create one, and what that costs.