Most export mistakes happen at process boundaries: a value works in your terminal but disappears in a child script, sudo command, cron job, or new shell. The export command in Linux marks shell variables for child processes, which is why it appears in build instructions, language-runtime setup, PATH changes, editor defaults, locale settings, and one-off application configuration.
Use export when a command launched from the current shell must inherit a variable. Use a temporary NAME=value command prefix when only one command needs the value, and put long-term settings in the right shell startup file instead of retyping them in every terminal.
Understand the export Command in Linux
The GNU Bash manual documents export as a shell builtin that sets the export attribute on shell variables and, with Bash’s function option, shell functions. The POSIX export utility defines the portable variable-export behavior and the -p listing form.
The key boundary is parent shell to child process. Exporting a variable does not change the parent process that started your shell, and it does not automatically edit future terminal sessions. It only affects commands launched after the export happens in the current shell session.
The examples use Bash, the default interactive shell on many Linux distributions. POSIX
shsupports exporting variables, but Bash-specific features such asexport -ffor functions andexport -nfor removing the export attribute should stay in Bash scripts.
Basic export Syntax
export [-fn] [name[=value] ...]
export -p
| Task | Command Form | What It Does |
|---|---|---|
| Export an existing variable | export NAME | Marks NAME so later child processes inherit it. |
| Set and export in one step | export NAME=value | Assigns the value in the current shell and exports it for later child processes. |
| List exported names | export -p | Prints exported variables in a shell-reusable form. |
| Stop exporting a variable | export -n NAME | Removes Bash’s export attribute while keeping the shell variable set. |
| Export a Bash function | export -f function_name | Makes the function available to child Bash processes. |
Common export Command Patterns
Most real export usage falls into a few repeatable patterns: lasting values for later commands, one-command overrides, PATH updates, trusted .env loading, startup persistence, and cleanup.
| Reader Task | Command Pattern | Use When |
|---|---|---|
| Set a value for later commands | export APP_ENV=production | The current shell should pass the value to commands launched afterward. |
| Set a value for only one command | APP_ENV=staging command_name | The setting should not remain in the current shell. |
| Add a user command directory | export PATH="$HOME/.local/bin:$PATH" | User-installed scripts should resolve before system commands. |
| Load trusted shell-style variables | set -a; source ./.env; set +a | A local file contains plain shell assignments that should become environment variables. |
| Make Bash startup persistent | export NAME=value in ~/.bashrc | Future interactive Bash terminals need the same setting. |
| Remove the variable completely | unset NAME | Neither the current shell nor later child processes should keep the value. |
Verify export Is a Shell Builtin
export is not a separate package to install. Use Bash’s type builtin to confirm how the current shell resolves it:
type export
export is a shell builtin
Bash also provides built-in help for the exact option set available in that shell:
help export | sed -n '1,2p'
export: export [-fn] [name[=value] ...] or export -p [-f]
Set export attribute for shell variables.
Some Bash versions print the second form as export -p without [-f]. Use help export on the shell that will run the script when exact option wording matters.
Use the printf command in Linux for predictable output when a shell script needs exact newlines or formatted status text.
Export Variables for Child Processes
A normal shell variable stays in the current shell unless you export it. Set DEMO_MODE, start a child Bash process before export, then start another child process after export:
DEMO_MODE=local
bash -c 'printf "Before export: %s\n" "${DEMO_MODE:-not available}"'
export DEMO_MODE
bash -c 'printf "After export: %s\n" "$DEMO_MODE"'
unset DEMO_MODE
Before export: not available After export: local
The first child process cannot see DEMO_MODE because the variable has not been exported yet. The second child process receives it through the environment created by the current shell.
Check an Exported Variable with printenv
printenv reads the environment, so it is a good way to prove that a variable is available to child processes:
export LC_EXPORT_DEMO=enabled
printenv LC_EXPORT_DEMO
enabled
Clean up the demo variable when you are finished with it:
unset LC_EXPORT_DEMO
Set and Export Variables in One Command
The compact form export NAME=value is useful when you are creating the variable and exporting it at the same time. Keep the assignment tight around the equals sign; spaces turn the line into a different command shape and usually cause an identifier error.
export APP_ENV=production
bash -c 'printf "APP_ENV=%s\n" "$APP_ENV"'
unset APP_ENV
APP_ENV=production
Quote values that contain spaces, shell characters, or paths built from variables:
export GREETING_MESSAGE="Hello from Linux"
bash -c 'printf "%s\n" "$GREETING_MESSAGE"'
unset GREETING_MESSAGE
Hello from Linux
Use uppercase names for variables intended to become environment variables. Lowercase names work in Bash, but uppercase names avoid collisions with ordinary local shell variables and match common environment-variable conventions.
Export Multiple Variables at Once
Bash accepts several assignments in one export command. Keep each assignment self-contained, and quote only the values that need quoting:
export APP_ENV=production LOG_LEVEL=info FEATURE_FLAG=true
bash -c 'printf "env=%s log=%s flag=%s\n" "$APP_ENV" "$LOG_LEVEL" "$FEATURE_FLAG"'
unset APP_ENV LOG_LEVEL FEATURE_FLAG
env=production log=info flag=true
Use separate lines when a value is long, generated, security-sensitive, or easier to review in a script. Dense one-line exports are convenient for short flags, but they become hard to troubleshoot when command substitution or quoting is involved.
Use Temporary Environment Variables for One Command
Not every environment variable needs to remain in the current shell. Prefix a single command with NAME=value when only that command and its children need the value:
unset LC_TEMP_MODE
LC_TEMP_MODE=staging bash -c 'printf "child: %s\n" "$LC_TEMP_MODE"'
printf 'current shell: %s\n' "${LC_TEMP_MODE:-unset}"
child: staging current shell: unset
This form is better than export for temporary build flags, test modes, and nonsecret application settings that should not leak into later commands in the same terminal.
Do not pass secrets through casual command-line environment examples. Shell history, process listings, logs, crash reports, and wrapper scripts can expose values depending on how a command runs. Prefer a credential file, prompt, secret manager, or tool-specific secure input path when the value is sensitive.
Load Environment Variables from a .env File
Many application projects keep local nonsecret settings in a .env file. Bash does not treat that file specially, but you can load trusted shell-style assignments with the source command in Linux and export them with set -a.
demo_dir=$(mktemp -d)
cat > "$demo_dir/.env" <<'EOF'
APP_ENV=staging
APP_PORT=8080
EOF
set -a
source "$demo_dir/.env"
set +a
bash -c 'printf "APP_ENV=%s APP_PORT=%s\n" "$APP_ENV" "$APP_PORT"'
unset APP_ENV APP_PORT
rm -rf "$demo_dir"
APP_ENV=staging APP_PORT=8080
set -a marks variables created or modified afterward for export. Turn it off with set +a immediately after loading the file so later shell variables do not become environment variables by accident.
sourceexecutes the file as shell code. Use this pattern only for a trusted file that you control, not for downloaded configuration, copied chat snippets, or unreviewed project files.
Use export with Scripts and Sourced Files
A script that you run normally is a child process, so its exports do not flow back into the terminal that launched it. Source the file when the current shell needs to keep the variable after the file finishes.
demo_dir=$(mktemp -d)
cat > "$demo_dir/set-env.sh" <<'EOF'
export LC_SCRIPT_DEMO=from-script
EOF
chmod +x "$demo_dir/set-env.sh"
unset LC_SCRIPT_DEMO
"$demo_dir/set-env.sh"
printf 'after running script: %s\n' "${LC_SCRIPT_DEMO:-unset}"
source "$demo_dir/set-env.sh"
printf 'after source: %s\n' "$LC_SCRIPT_DEMO"
unset LC_SCRIPT_DEMO
rm -rf "$demo_dir"
after running script: unset after source: from-script
Use normal script execution for programs that should not alter your terminal. Use source for shell setup files, environment switchers, language-runtime activation scripts, and other files whose purpose is to change the current shell.
List Exported Variables with export -p
export -p prints variables that currently have the export attribute. The full list is usually long, so filter it when you are checking one name:
export LC_EXPORT_DEMO=enabled
export -p | grep 'LC_EXPORT_DEMO'
Relevant Bash output includes:
declare -x LC_EXPORT_DEMO="enabled"
Bash also prints exported variables when you run export without arguments, but portable scripts should use export -p. Remove the demo variable when you are done:
unset LC_EXPORT_DEMO
Add Directories to PATH with export
PATH is one of the most common variables changed with export. It controls where the shell looks for commands, so keep edits explicit and reversible while testing.
old_path=$PATH
export PATH="$HOME/.local/bin:$PATH"
printf '%s\n' "$PATH" | tr ':' '\n' | sed -n '1,3p'
PATH=$old_path
The first printed path should be your user’s ~/.local/bin directory, followed by the earlier path entries. Use $HOME instead of a hard-coded username so the line works when copied between accounts.
If a command still resolves to the wrong executable after a PATH change, use the which command in Linux or Bash’s type -a command_name to see which path the shell finds first.
Avoid Duplicate PATH Entries
Repeatedly sourcing a startup file can add the same directory to PATH again and again. Guard the export when the line may run more than once:
case ":$PATH:" in
*":$HOME/.local/bin:"*) ;;
*) export PATH="$HOME/.local/bin:$PATH" ;;
esac
The surrounding colons make the check match complete path entries only. Without them, a directory such as /home/user/.local/bin-tools could look like a match for /home/user/.local/bin.
Common Environment Variables to Export
The same export NAME=value pattern appears in many Linux workflows. The variable name matters because each application decides which environment variables it reads.
| Task | Example Export | Practical Note |
|---|---|---|
| Choose the default terminal editor | export EDITOR=nano | Many command-line tools read EDITOR when opening an editor. |
| Prefer a visual editor when supported | export VISUAL=nano | Set both VISUAL and EDITOR when a tool checks one before the other. |
| Add user-installed commands | export PATH="$HOME/.local/bin:$PATH" | Put the new directory first only when user commands should win over system commands. |
| Point tools at a JDK root | export JAVA_HOME="$HOME/.local/jdk-21" | Replace the path with the actual JDK root; do not guess a distro-specific system path. |
| Send tools through a proxy | export HTTPS_PROXY="http://proxy.example.com:8080" | Use tool documentation for exact proxy variable support, and avoid proxy URLs with embedded credentials. |
| Bypass proxy for local targets | export NO_PROXY="localhost,127.0.0.1,.example.com" | Keep the list specific so local services and private domains do not route through the proxy. |
Locale variables such as LANG, LC_ALL, and LC_COLLATE can change sorting, character handling, and program messages. For one command, prefer a temporary prefix such as LC_ALL=C command_name instead of exporting a locale globally in every terminal.
Make export Persistent in Bash Startup Files
An exported variable lasts only for the current shell session and child processes created from it. Put long-term Bash settings in a startup file when future terminals need the same value.
For interactive Bash terminals, add lines like these near the end of ~/.bashrc:
export EDITOR=nano
export PATH="$HOME/.local/bin:$PATH"
Reload the file in the current terminal when you want the changes immediately:
source ~/.bashrc
The source command matters here because it runs the startup file in the current shell. Running bash ~/.bashrc would start a child shell and lose the variables when that child exits.
Use ~/.profile, ~/.bash_profile, or another login-shell file only when the variable must be present for login sessions. Desktop environments, display managers, systemd user services, and non-Bash shells can use different startup paths, so match the file to the session that needs the variable.
Know When export Is Not the Right Tool
export changes the environment for the current shell and its future child processes. It is not a universal Linux settings database, so some workflows need a different mechanism.
| Workflow | Why export Is Not Enough | Better Place to Set the Value |
|---|---|---|
| systemd services | Services do not read your interactive ~/.bashrc. | Use service unit settings such as Environment= or an environment file managed by the service. |
| cron jobs | Cron starts commands with a limited environment and does not load normal interactive shell startup files. | Set variables in the crontab, call a wrapper script, or load a controlled environment file inside the job. |
| Dockerfiles | A shell export inside one build step does not automatically become image metadata for later runtime containers. | Use Dockerfile instructions such as ENV when the image should carry the variable. |
| Secrets and tokens | Environment variables can leak through history, process metadata, logs, or crash reports depending on the tool. | Use the tool’s secure credential store, prompt, file permission model, or secret manager. |
| Other shells | Fish, C shell variants, and other shells use different syntax. | Use that shell’s native environment-variable syntax instead of copying Bash examples. |
This boundary also explains why copying export lines into the wrong file can look random. The variable works only in sessions that read that file before launching the command that needs the value.
Remove Exported Variables or Export Attributes
Use unset when the variable should disappear from the current shell. Use Bash’s export -n when the current shell should keep the variable but stop passing it to child processes.
export LC_EXPORT_DEMO=enabled
export -n LC_EXPORT_DEMO
printf 'Current shell: %s\n' "$LC_EXPORT_DEMO"
bash -c 'printf "Child shell: %s\n" "${LC_EXPORT_DEMO:-not exported}"'
unset LC_EXPORT_DEMO
Current shell: enabled Child shell: not exported
export -n is useful when a later command should not inherit an earlier setting. Use unset LC_EXPORT_DEMO when neither the current shell nor later child processes should keep the variable.
Export Bash Functions Carefully
Bash can export functions for child Bash processes with export -f. Keep this for controlled Bash-to-Bash workflows; reusable production functions are usually clearer when stored in a script or sourced helper file.
show_message() { printf 'message from exported function\n'; }
export -f show_message
bash -c 'show_message'
unset -f show_message
message from exported function
export -f is not portable to POSIX sh. If a script might run under dash, BusyBox sh, or another minimal shell, put the function body in a script file and run that script directly.
Use export Safely in Scripts
export is simple, but a few patterns prevent confusing shell behavior from becoming hard-to-find bugs.
Treat Exported Values as Strings
The process environment stores strings. Bash arrays, associative arrays, shell options, aliases, and most shell-only state do not become real environment objects just because you use export.
colors=(red blue)
export colors
bash -c 'printf "colors: %s\n" "${colors:-unset}"'
unset colors
colors: unset
When a child process needs several values, pass a delimiter-separated string, a file path, JSON, or command arguments that the receiving program knows how to parse.
Use Valid Names and Tight Assignments
Shell assignments use NAME=value with no spaces around the equals sign. A line such as export APP_ENV = debug is parsed as separate words, not as one assignment.
bash -c 'export APP_ENV = debug'
Bash reports that one of the parsed words is not a valid identifier:
bash: line 1: export: `=': not a valid identifier
Use letters, numbers, and underscores for names, with a letter or underscore first:
export APP_MODE=debug
Do Not Hide Command-Substitution Failures
In Bash, export NAME=$(command) can hide a failing command substitution because the final status belongs to export. The next short example proves the risk with false:
export LC_BAD_VALUE=$(false)
printf 'export status: %s\n' "$?"
export status: 0
Assign first, check the command status, then export the variable only after the value exists:
if LC_GOOD_VALUE=$(printf 'ready'); then
export LC_GOOD_VALUE
printf 'safe value: %s\n' "$LC_GOOD_VALUE"
fi
unset LC_GOOD_VALUE
safe value: ready
Pass Variables through sudo Explicitly
Most sudo policies sanitize the environment. If a privileged command needs a nonsecret value from your shell, pass only that variable explicitly with sudo env:
export LC_SUDO_DEMO=visible
sudo env LC_SUDO_DEMO="$LC_SUDO_DEMO" sh -c 'printf "%s\n" "$LC_SUDO_DEMO"'
unset LC_SUDO_DEMO
visible
Do not use broad sudo -E by habit. It preserves more environment state than most commands need and can create confusing differences between user and root contexts.
Troubleshoot Common export Command Problems
Variable Is Empty in a Child Command
A variable that prints in the current shell but disappears in a child command usually was assigned but not exported. Check both layers:
printf 'shell value: %s\n' "${APP_ENV:-unset}"
bash -c 'printf "child value: %s\n" "${APP_ENV:-unset}"'
If the shell value exists but the child value says unset, export the variable before launching the child command:
export APP_ENV
Script Exports a Variable but the Terminal Does Not See It
A normally executed script cannot update the parent shell’s environment. If a setup file is meant to change your current terminal, run it with source instead of executing it as a child process.
source ./set-env.sh
printf 'current shell: %s\n' "${LC_SCRIPT_DEMO:-unset}"
Replace ./set-env.sh with the real setup file. If the file came from another project or the internet, read it first because source runs every command inside it in your current shell.
.env File Does Not Load
A .env file loaded with source must be valid shell syntax. Check the file before loading it into the current shell:
bash -n ./.env
No output means Bash accepted the syntax. If the file contains spaces, quote the value instead of adding spaces around the equals sign:
APP_NAME="Demo App"
APP_PORT=8080
After the syntax check passes and you trust the file, load it with set -a, source ./.env, and set +a.
Export Disappears in a New Terminal
A new terminal starts a new shell process. If the variable is not in a startup file or session environment, the new shell never receives it. Check the files your shell actually reads, then add the export line to the right one.
grep -n 'APP_ENV' ~/.bashrc ~/.profile 2>/dev/null
Add the line to ~/.bashrc for interactive Bash terminals, then reload it with source ~/.bashrc or open a new terminal.
Command Still Not Found After Changing PATH
A PATH export affects commands launched after the change. If the shell still cannot find a command, confirm the directory exists, confirm the executable bit, then inspect shell resolution:
printf '%s\n' "$PATH" | tr ':' '\n'
type -a command_name
Replace command_name with the real command. If the expected directory is missing, reapply the export PATH=... line or reload the startup file that contains it.
Export Works in the Terminal but Not in cron or systemd
A value that works in your terminal proves only that the current shell has it. Cron jobs and systemd services start from their own environment and usually do not read interactive Bash startup files.
printenv APP_ENV
If printenv shows the expected value in your terminal but the job or service still misses it, move the value into the scheduler or service configuration that launches that process. Do not keep adding export lines to ~/.bashrc when the process never reads that file.
sudo Command Ignores an Exported Variable
sudo may reset the environment even when the variable is exported in your user shell. Verify the value is present before sudo:
printenv LC_SUDO_DEMO
When the value exists for your user but not inside the privileged command, pass the one required variable explicitly:
sudo env LC_SUDO_DEMO="$LC_SUDO_DEMO" command_name
Replace command_name with the real privileged command, and avoid this pattern for secrets unless the tool’s documentation says environment variables are the intended secure input path.
Exported Array Is Empty in a Child Shell
Bash arrays are shell data structures, not environment variables. If a child shell needs several values, export a string representation or pass a file path that the child process can read.
export COLORS="red:blue"
bash -c 'printf "COLORS=%s\n" "$COLORS"'
unset COLORS
COLORS=red:blue
Choose a delimiter that cannot appear in the values, or use a structured file format when values can contain spaces, colons, newlines, or shell-sensitive characters.
Conclusion
Environment variables are now scoped deliberately: startup files for future Bash terminals, exported values for later child processes, one-command prefixes for temporary overrides, trusted .env loading for project settings, and native service or scheduler configuration when a shell is not the parent process. Keep secrets out of casual export lines, and verify inheritance with printenv, export -p, or a child Bash check before troubleshooting the application.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><a href="https://example.com">link</a><blockquote>quote</blockquote>