Bash – Use env with environment variables from file

bashenvironment-variablesshell

Let's say I have a file (called e) with this content:

a=3
b="5 6"

How can I get each one to be interpreted as a separate argument to env? That is, to have it equivalent to:

$ env a=3 b="5 6" ruby -e 'p ENV["a"]; p ENV["b"]'
"3"
"5 6"
$ env a=3 "b=5 6" ruby -e 'p ENV["a"]; p ENV["b"]'
"3"
"5 6"

This one obviously doesn't work because of the space:

env $(cat e) ruby -e 'p ENV["a"]; p ENV["b"]'

But neither does this one:

IFS=$'\n' env $(cat e) ruby -e 'p ENV["a"]; p ENV["b"]'

And quoting $(cat e) will result in:

"1\nb=2 3"
nil

Best Answer

This is an example of not using the right tool for the job. env isn't the only tool that sets environment variables and then chain loads another program. And it doesn't read variable data from file.

Of course, the . a.k.a. source command is not the right tool for this job, either.

  1. It permits the file to unexpectedly contain shell commands other than simple variable assignments, which in certain circumstances (depending from what the configuration file is) can be a massive security hole.
  2. A series of assignments as in the example in the question, sourced by ., sets shell variables, not environment variables. They aren't automatically exported.

The right tools are ordinary chain-loading tools from several toolsets of such tools.

One such is read-conf from the nosh toolset, designed to read exactly this kind of configuration file (such as /etc/rc.conf from — say — PC-BSD) and set environment variables without implementing and opening up configuration data files to an entire shell language syntax:

jdebp % uname
Linux
jdebp % cat e
a=3
b="5 6"
jdebp % read-conf e printenv | tail -n 3
USER=jdebp
a=3
b=5 6
jdebp %
jdebp % uname
FreeBSD
jdebp % read-conf /etc/rc.conf printenv | head -n 2
cron_enable=NO
sendmail_msp_queue_enable=NO
jdebp %

Another such tool is Wayne Marshall's runenv from perp.

Related Question