Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This question already has an answer here:

What's the difference and which is better to use when customizing my bash profile? Documentation on the export command is scarce, as it's a builtin cmd.

Excerpt from version 1 of my ~/.bash_profile:

#PATH
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:$HOME/bin

#add Homebrew’s sbin to PATH
export PATH=/usr/local/sbin:$PATH

Output from: echo $PATH /usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/njboot/bin

Excerpt from version 2:

#PATH
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:$HOME/bin

#add Homebrew’s sbin to PATH
export PATH=/usr/local/sbin:$PATH

Output from echo $PATH is the same as in version 1. env is the same as well.

So:

  • 1) What's the benefit of using export vs. setting PATH explicitly?
  • 2) Is there any functional difference between version 1 and version 2 when applied?
  • 3) Which should I use and why?
share|improve this question

marked as duplicate by Gilles Jun 23 at 1:11

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1  
For whatever reason @Gilles has apparently marked this question as a duplicate of one for which he has the accepted answer (though just before doing so he did edit his three-years-old answer), despite five other users already marking another question as a duplicate of this one only five hours ago and two other users in chat arguing against closing this question when he first proposed it last night. Strangest of all he waited until after this question had an accepted answer to do so. –  mikeserv Jun 23 at 1:57
1  
@mikeserv The question is related, though not a duplicate IMO-I looked at the markdown, and Gilles edits to his accepted answer support the fact that my question is not in fact a duplicate. Logically, if it were a duplicate, there would have been no need to edit the answer in the other question, right? Seems odd behavior for a community mod...in any case, your answer directly addressed my question and was exactly the one I was looking for. –  njboot Jun 23 at 3:15
    
@njboot I asked around in chat and didn't get a strong response one way or the other. I started to write an answer here and found that it was pretty much repeating what I'd written before, so I closed as a duplicate. When I re-read my old answer, I found a couple of things I wanted to tweak. What do you think is missing in the old thread? –  Gilles Jun 23 at 7:43
1  
@Gilles - in fact you received two responses. The only two people in the chat room both responded. The first said: "that seems more like 'setting VAR vs. exporting VAR in ~/.bash_profile' if we forget about 'PATH' and treat them as variables we can get something canonical..." and again persisted: "...is my impression, going by the first lines, that he's more interested in the different ways to set variables (customizing his shell) than the special case of PATH". The second said: "I agree with you, he's more interested in the meaning of export." Nothing further was said on the matter. –  mikeserv Jun 23 at 15:02
add comment

2 Answers

up vote 2 down vote accepted

To answer your questions specifically:

  1. export does set the $PATH explicitly.

  2. No. export sets environment for child processes, but $PATH is already set for the current environment. So, in the second example, when the command is read-in - and before export is executed - the current environment's value for $PATH is expanded into the $PATH word.

  3. You should use whichever is necessary and/or comfortable for you. Neither makes any difference functionally, so this is primarily a question of style.

POSIX defines the export builtin so:

The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.

From another of my answers:

There is little difference between declaring a shell variable and an environment variable. Because export is a builtin it declares an environment variable for the process next invoked, but if you don't invoke one that process remains the shell, and so your variable is twice evaluated.

You can remove all exports without any effect at all on exported variables so long as you don't use export to twice evaluate. By twice evaluate I mean:

var1=var2 
export "${var1}=var3"
echo "$var2"
var3

Instead just use:

set -a 

...at the top of the script. All variables defined thereafter will be automatically exported - which would include variables you might not have previously exported. Alternatively you could only set -a for a portion of the script and later set +a to unset it - it could also work as function.

But subshells automatically inherit variable values anyway, so:

var1=value
( echo "$(echo "$var1")" )
value

export makes no difference in that case.

But if your script calls another script, or any other executable that interprets values you've exported and you cease to export them, then those values will no longer be available in their environment. In the following example I use the shell variable $PS1 - which defines the contents of an interactive shell's prompt - to demonstrate how variations on exported variables affect child processes.

export PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i

###OUTPUT###

this is another executable
 > exit
exit

But ...

PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i

###OUTPUT###

sh-4.3$ exit
exit

But then again, if you explicitly declare environment variables while invoking a process...

PS1="$(printf "this is another executable\n > ")"
{
echo exit | PS1=$PS1 sh -i
echo exit | sh -i
}

###OUTPUT###

this is another executable
 > exit
exit
sh-4.3$ exit
exit

Any of the ENV files first invoked by a shell such as .bashrc or .profile will set variable values for the life of that shell. So any variables that are set and exported within those files will maintain that export characteristic and be exported to all child processes invoked by that shell for the life of the shell or until they are unset.

It is notable, though, that bash extends the export builtin somewhat to include the -n option - which enables you to remove the export attribute from a variable without unsetting it, but this is not portable behavior.

share|improve this answer
add comment

Here's a similar thread.

A short answer:

http://superuser.com/a/153378/333431

Exported variables get passed on to child processes, not-exported variables do not.

This means you should export your variables, if you intend to use them in subshells.

You can test this:

$ TEST="im_not_here"
$ echo $TEST
im_not_here
$ bash -c 'echo $TEST'
<empty output>
$ export TEST2="im_here"
$ echo $TEST2
im_here
$ bash -c 'echo $TEST2'
im_here
share|improve this answer
1  
You should clarify what you mean by subshells. var=val ; (echo $var) still yields val. –  mikeserv Jun 22 at 15:44
    
And yet PATH=/usr/local/sbin:$PATH would work equally well without the export: once a variable is exported, it stays exported, and further assignments modify the environment variable. Furthermore, to clarify mikeserv's comment, you don't need export to use variables in subshells, you need them to use them in child programs. Subshell is a technical term, meaning a forked copy of the running shell. (echo $var) runs echo $var` in a subshell and sees the original shell's internal variable; sh -c 'echo $var' runs echo $var in a child program and only sees environment variables. –  Gilles Jun 25 at 7:58
add comment

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