101

What's the difference between:

a=b

and

export a=b

In bash?

I understand that they both define environment variables, but I don't fully understand the difference.

Kenny Evitt
  • 453
  • 5
  • 16
Adam Matan
  • 8,740

5 Answers5

98

export propagates the variable to subprocesses.

For example, if you did

FOO=bar

then a subprocess that checked for FOO wouldn't find the variable whereas

export FOO=bar

would allow the subprocess to find it.

But if FOO has already been defined as an environment variable, then FOO=bar will modify the value of that environment variable.

For example:

FOO=one     # Not an environment variable
export FOO  # Now FOO is an environment variable
FOO=two     # Update the environment variable, so sub processes will see $FOO = "two"

Older shells didn't support the export FOO=bar syntax; you had to write FOO=bar; export FOO.

Mike McQuaid
  • 4,187
49

If you don't use export, you're not defining an environment variable; just a shell variable.

Shell variables are only available to the shell process; environment variables are available to any subsequent process, not just shells.

wfaulk
  • 6,307
5

Also, if you want to have the variable available to the calling shell without using export you can do this:

File a.ksh is -

#!/bin/ksh
FOO=bar

On the prompt, run this is

> . a.ksh

This will run the commands within the same shell and $FOO will be available.

Whereas,

> a.ksh

Will make $FOO available only within a.ksh, after the call to a.ksh it would not exist.

alok
  • 418
2

In addition to what has already been answered, both of these statement do not necessarily define (i.e. create vs set) an environment variable as "a" might already exist as a shell or environment variable.

In the latter case, both statements are strictly equivalent.

jlliagre
  • 14,369
1

A script to demonstrate effect of export (let's call it export-demo.sh):

#!/bin/bash

Just function definition, no code executed here yet

function some_function() { echo " function:var: $var" #local var var="Set in function" echo " function:var: $var" }

Define variable

var="Set in top script" #export var

echo script:var: $var

This is sub-shell

( echo " sub-shell:var: $var" var="Set in sub-shell" echo " sub-shell:var: $var" )

echo script:var: $var

This sub-process (could be any executable actually)

bash -c ' echo " sub-process:var: $var" var="Set in sub-process" echo " sub-process:var: $var" '

This script function call

echo script:var: $var some_function echo script:var: $var

Executed without export (it's commented out) produce this output:

$ bash export-demo.sh; echo shell: $var
script: Set in top script
  sub-shell: Set in top script
  sub-shell: Set in sub-shell
script: Set in top script
  sub-process: 
  sub-process: Set in sub-process
script: Set in top script
  function: Set in top script
  function: Set in function
script: Set in function
shell:

As we can see, script-level defined variable:

  • passed to sub-shell and changes not propagated up to script-level. It's because sub-shell gets copy of variable of the upper script;
  • passed to function, and can be changed from there (because function variable is not defined as local, see below);
  • not passed to sub-process.

Let's un-comment export var line and run the script again:

$ bash export-demo.sh; echo shell: $var
script:var: Set in top script
  sub-shell:var: Set in top script
  sub-shell:var: Set in sub-shell
script:var: Set in top script
  sub-process:var: Set in top script
  sub-process:var: Set in sub-process
script:var: Set in top script
  function:var: Set in top script
  function:var: Set in function
script:var: Set in function
shell:

That's exactly what export does: it exports shell variable as process environment variable for sub-processes, which the script may spawn. No changes from sub-process propagated to upper script (because it's also gets copy of original variable).

Please, note, no changes to upper shell done (last output line). It's because script run from shell as sub-process, even if called as:

$ chmod +x export-demo.sh; ./export-demo.sh

(An only way to get rid of sub-processing script on run is to source it to current shell session as noted in this answer.)

Bonus. Let's un-comment local var line and run the script again:

$ bash export-demo.sh; echo shell: $var
script:var: Set in top script
  sub-shell:var: Set in top script
  sub-shell:var: Set in sub-shell
script:var: Set in top script
  sub-process:var: Set in top script
  sub-process:var: Set in sub-process
script:var: Set in top script
  function:var: Set in top script
  function:var: Set in function
script:var: Set in top script
shell:

As we can see, variable defined as local in function gets copy of upper script and can't change upper script variable value.

dess
  • 626