How to export variables from a file?

set -a
. ./tmp.txt
set +a

set -a causes variables¹ defined from now on to be automatically exported. It's available in any Bourne-like shell. . is the standard and Bourne name for the source command so I prefer it for portability (source comes from csh and is now available in most modern Bourne-like shells including bash though (sometimes with a slightly different behaviour)).

In POSIX shells, you can also use set -o allexport as a more descriptive alternative way to write it (set +o allexport to unset).

You can make it a function with:

export_from() {
  # local is not a standard command but is pretty common. It's needed here
  # for this code to be re-entrant (for the case where sourced files to
  # call export_from). We still use _export_from_ prefix to namespace
  # those variables to reduce the risk of those variables being some of
  # those exported by the sourced file.
  local _export_from_ret _export_from_restore _export_from_file

  _export_from_ret=0

  # record current state of the allexport option. Some shells (ksh93/zsh)
  # have support for local scope for options, but there's no standard
  # equivalent.
  case $- in
    (*a*) _export_from_restore=;;
    (*)   _export_from_restore='set +a';;
  esac

  for _export_from_file do
    # using the command prefix removes the "special" attribute of the "."
    # command so that it doesn't exit the shell when failing.
    command . "$_export_from_file" || _export_from_ret="$?"
  done
  eval "$_export_from_restore"
  return "$_export_from_ret"
}

¹ In bash, beware that it also causes all functions declared while allexport is on to be exported to the environment (as BASH_FUNC_myfunction%% environment variables that are then imported by all bash shells run in that environment, even when running as sh).


source tmp.txt
export a b c
./child ...

Judging by your other question, you don't want to hardcode the variable names:

source tmp.txt
export $(cut -d= -f1 tmp.txt)

test it:

$ source tmp.txt
$ echo "$a $b $c"
123 hello world one more variable
$ perl -E 'say "@ENV{qw(a b c)}"'

$ export $(cut -d= -f1 tmp.txt)
$ perl -E 'say "@ENV{qw(a b c)}"'
123 hello world one more variable

A dangerous one-liner that doesn't require source:

export $(xargs <file)
  • It can't handle comments, frequently used in environment files
  • It can't handle values with whitespace, like in the question example
  • It may unintentionally expand glob patterns into files if they match by any chance

It's a bit dangerous because it passes the lines through bash expansion, but it has been useful to me when I know I have safe environment files.

Tags:

Bash