Setting PATH vs. exporting PATH in ~/.bash_profile

  • 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?
  • mikeserv

    mikeserv Correct answer

    6 years ago

    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.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM