33

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

var=value
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"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

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.

3
  • 2
    thanks I finally understood why I see so often the thing that I thought was useless: var=value;export var Commented Mar 28, 2015 at 15:56
  • 3
    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.) Commented Mar 28, 2015 at 16:07
  • Thanks Ulrich, Solaris may well be the culprit why this long syntax is still around. Commented Mar 28, 2015 at 16:09

2 Answers 2

32

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 assignment:

$ 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.

5
  • Many thanks for the historical insight and the correct error message to google for! Obvious in retrospect, blush...
    – tripleee
    Commented Mar 28, 2015 at 17:31
  • 5
    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 Commented Mar 28, 2015 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
    Commented Mar 28, 2015 at 22:00
  • @jeffSchaller Thanks for correcting affectation, a false friend as it means "assignment" in French. On the other hand, to Google is controversial
    – jlliagre
    Commented Jan 24, 2022 at 15:25
  • 1
    Ahhh, I haven't learned enough French to recognize affectation; thanks for the background! I've also just learned about the xerox effect when it comes to verbs, so I'm happy to revert that change.
    – Jeff Schaller
    Commented Jan 24, 2022 at 15:28
24
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

or:

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).

While

export \d=$a

or

var=d
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).

9
  • 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
    Commented Apr 1, 2015 at 14:23
  • 4
    @jrw32982, because it's a builtin. You still get that in modern POSIX shells but only for special builtins which export is. Commented Apr 1, 2015 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
    Commented Nov 26, 2015 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
    Commented Jul 3, 2018 at 11:12
  • @conny, d=$a export d doesn't work anymore in zsh, so I've updated the answer. See edit. Commented Jul 3, 2018 at 13:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .