I have picked up -- probably on Usenet in the mid-1990s (!) -- that the construct

export var=value

is a Bashism, and that the portable expression is

export var

I have been advocating this for years, but recently, somebody challenged me about it, and I really cannot find any documentation to back up what used to be a solid belief of mine.

Googling for "export: command not found" does not seem to bring up any cases where somebody actually had this problem, so even if it's genuine, I guess it's not very common.

(The hits I get seem to be newbies who copy/pasted punctuation, and ended up with 'export: command not found or some such, or trying to use export with sudo; and newbie csh users trying to use Bourne shell syntax.)

I can certainly tell that it works on OS X, and on various Linux distros, including the ones where sh is dash.

sh$ export var=value
sh$ echo "$var"
sh$ sh -c 'echo "$var"'  # see that it really is exported

In today's world, is it safe to say that export var=value is safe to use?

I'd like to understand what the consequences are. If it's not portable to v7 "Bourne classic", that's hardly more than trivia. If there are production systems where the shell really cannot cope with this syntax, that would be useful to know.

  • 2
    thanks I finally understood why I see so often the thing that I thought was useless: var=value;export var – Thorsten Staerk Mar 28 '15 at 15:56
  • 2
    There's still a few Solaris boxes kicking around, and those are notoriously frugal in their standard tools; on the other end of the spectrum, doesn't busybox come with its own minimal shell? (I am not in a position to try either right this second.) – Ulrich Schwarz Mar 28 '15 at 16:07
  • Thanks Ulrich, Solaris may well be the culprit why this long syntax is still around. – Thorsten Staerk Mar 28 '15 at 16:09
export foo=bar

was not supported by the Bourne shell (an old shell from the 70s from which modern sh implementations like ash/bash/ksh/yash/zsh derive). That was introduced by ksh.

In the Bourne shell, you'd do:

foo=bar export foo


foo=bar; export foo

or with set -k:

export foo foo=bar

Now, the behaviour of:

export foo=bar

varies from shell to shell.

The problem is that assignments and simple command arguments are parsed and interpreted differently.

The foo=bar above is interpreted by some shells as a command argument and by others as an assignment (sometimes).

For instance,

a='b c'
export d=$a

is interpreted as:

'export' 'd=b' 'c'

with some shells (ash, older versions of zsh (in sh emulation), yash) and:

'export' 'd=b c'

in the others (bash, ksh).


export \d=$a


export $var=$a

would be interpreted the same in all shells (as 'export' 'd=b' 'c') because that backslash or dollar sign stops those shells that support it to consider those arguments as assignments.

If export itself is quoted or the result of some expansion (even in part), depending on the shell, it would also stop receiving the special treatment.

See "Are quotes needed for local variable assignment?" for more details on that.

The Bourne syntax though:

d=$a; export d

is interpreted the same by all shells without ambiguity (d=$a export d would also work in the Bourne shell and POSIX compliant shells but not in recent versions of zsh unless in sh emulation).

It can get a lot worse than that. See for instance that recent discussion about bash when arrays are involved.

(IMO, it was a mistake to introduce that feature).

  • I was surprised that the semicolon is not required in foo=bar export foo, as I had always seen it there. I know export is a builtin, but why does foo=bar; foo=baz export foo; echo $foo behave differently than foo=bar; foo=baz /bin/cat /dev/null; echo $foo? – jrw32982 Apr 1 '15 at 14:23
  • 3
    @jrw32982, because it's a builtin. You still get that in modern POSIX shells but only for special builtins which export is. – Stéphane Chazelas Apr 1 '15 at 14:26
  • Although it discusses declare, not export, I recommend that anyone who cares about security read the discussion at the link that StéphaneChazelas provided to bash.bugs. – John1024 Nov 26 '15 at 0:14
  • Great answer! But it took a long time to get to d=$a export d is interpreted the same by all shells without ambiguity ;-) – conny Jul 3 '18 at 11:12
  • @conny, d=$a export d doesn't work anymore in zsh, so I've updated the answer. See edit. – Stéphane Chazelas Jul 3 '18 at 13:19

It is not a bashism but a POSIX compliant syntax. It actually started as a kshism quite a long time ago and was later adopted by almost all Bourne syntax based shells. The only notorious exception is /bin/sh on Solaris 10 and older which sticks to the legacy Bourne shell syntax. Hopefully, Solaris 11 uses a POSIX compliant shell as /bin/sh.

By the way, export was already a builtin command in the legacy Bourne shell so googling for export: command not found was misleading.

Here is the legacy Bourne shell behavior when export is combined with an affectation:

$ export var=22
var=22: is not an identifier

For the nostalgics, the source code of this original Bourne shell is available and can be compiled for most Unix and Linux distributions.

  • Many thanks for the historical insight and the correct error message to google for! Obvious in retrospect, blush... – tripleee Mar 28 '15 at 17:31
  • 4
    That's not the source code of the original Bourne shell, that's a modified OpenSolaris sh. It is the Bourne shell but after having undergone decades of evolution. The original Bourne shell, as shipped with Unix V7 can be found at the Unix Heritage Society – Stéphane Chazelas Mar 28 '15 at 21:34
  • 1
    @StéphaneChazelas Strictly speaking, you are as usual correct. Note however that I didn't wrote "the original Bourne shell" but "this original Bourne shell" as I was referring to the shell used by Solaris 10 and its source code that can be compiled on modern platforms. Note also that the Bourne shell had several features added between 1977 and 1989 but then essentially ceased to evolve (outside porting/adapting to newer platforms and bug fixes) in the last 25 years or so. – jlliagre Mar 28 '15 at 22:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.