I have a tmp.txt
file containing variables to be exported, for example:
a=123
b="hello world"
c="one more variable"
How can I export all these variables using the export
command, so that they can later be used by child processes?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityset -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
grep
to skip comments: export $(grep --regexp ^[A-Z] tmp.txt | cut -d= -f1)
source .env && export $(sed '/^#/d' .env | cut -d= -f1)
Jun 15, 2021 at 13:21
A dangerous one-liner that doesn't require source:
export $(xargs <file)
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.
If **utility** is omitted, echo(1) is used
Just do:
while read LINE; do export "$LINE"; done < ./tmp.txt
source
processing (arbitrary script execution).
Just complementing @Stéphane Chazelas ' excellent answer you can also use set -a
/set +a
and its counterparts inside a file (eg. "to_export.bash") like this...
#!/usr/bin/env bash
set -a
SOMEVAR_A="abcd"
SOMEVAR_B="efgh"
SOMEVAR_C=123456
set +a
... and then export all the variables contained in the file like this...
. ./to_export.bash
... or...
source ./to_export.bash
Thanks! 🤗
I've put together a solution that seems to be working in all cases (spaces, comments, etc) by using various proposed solutions. Here it is:
eval $(egrep "^[^#;]" .env | xargs -d'\n' -n1 | sed 's/^/export /')
. ./export_env_file.sh .env
in order for this to work
Oct 23, 2022 at 14:03
This solution will export all key=values
to environment variables that are in .env
file, that are not empty lines or commented (#
).
File: .env
ENV=local
DEBUG=True
Command:
$ export $(cat .env | egrep -v "(^#.*|^$)" | xargs)
My take:
dotenv() {
local REPLY
while read; do
REPLY=$(printf %s\\n "${REPLY%%#*}" | xargs)
[[ -n $REPLY ]] && export "$REPLY"
done < <(envsubst)
}
Supports comments, processes spaces, quotes & backslashes (xargs-processing), and expands environment variables. Avoids arbitrary script execution from source
.
Without xargs
& envsubst
, the syntax changes a bit (no unquoting or general post-processing), but comments are still supported and the function is bash-only.
Can be further improved to provide nicer error messages in bad lines.
You don't need to run export
on the content of a line, you just use it to mark the symbols you want to be exported. I use this function:
sourcery () {
local file vars
for file; do
# shellcheck disable=SC1090
source "$file" && {
mapfile -t vars < <(sed -nE '/^[[:space:]]*#/d;s/^[[:space:]]*([[:alpha:]_][[:alnum:]_]*)=.*/\1/p' "$file")
export "${vars[@]}"
}
done
}
This will source each file you pass to it and then read those files looking for uncommented variable declarations. It will mark each of the variables it finds as exported.
This is relatively safe because it relies on your shell to actually parse and resolve the content of the env file and only does string munging to figure out which symbols should get the export bit.
My version assumes bash
and a sed
supporting -E
, but you could write a highly portable version of the same idea without too much trouble.
little workaround based on one of answers:
~/.bashrc
function myenvs() {
if [ -z "$1" ]; then
echo "Usage: myenvs [import file path]";
else
if [ -f "$1" ]; then
source "$1" 2>/dev/null; export $(cat "$1" | grep "=" | grep -v "^#" | awk /./ | cut -d= -f1 | xargs)
else
echo "Bad file path: $1"
fi
fi
}
$ myenvs /path/to/env/file
to import envs※ if env/file
has bad lines, here are errors may be appeared when source
called. I just hide it, so error handling is up on you
.env
files when youcd
into a directory.