1

Say I have this .env file:

A=1
B=2
C="3 4 5"

If I run set -x; echo $(cat .env | xargs):

++ cat .env
++ xargs
+ echo A=1 B=2 C=3 4 5
A=1 B=2 C=3 4 5

If I run set -x; export $(cat .env | xargs):

++ cat /tmp/test.env
++ xargs
+ export A=1 B=2 C=3 4 5
+ A=1
+ B=2
+ C=3
bash: export: `4': not a valid identifier
bash: export: `5': not a valid identifier

Then I tried a lot of other tricks to try and keep or add quotes around the C value:

$ set -x; export $(cat /tmp/test.env | xargs printf %q)
+ set -x
++ cat /tmp/test.env
++ xargs printf %q
+ export ''\''A=1'\'''\''B=2'\'''\''C=3' 4 '5'\'''
bash: export: `'A=1''B=2''C=3': not a valid identifier
bash: export: `4': not a valid identifier
bash: export: `5'': not a valid identifier

No matter what I do, the C value is always split on spaces.

Edit: To clarify, a solution based on naively sourcing the .env file(most solutions from How to export variables from a file?) is severely unsafe, if the file contains any string that can be interpreted as command executon. I want my environment files to be interpreted only as key-value data.

  • 4
    What is your goal? Do you need . .env? – Arkadiusz Drabczyk Sep 24 at 14:44
  • you could do something like this: . <(sed -E -n '/^\s*[[:alpha:]_][[:alnum:]_]*=/ s/^/export /p' < .env). The sed command adds "export " to the beginning of lines that look like a valid variable assignment, and drops all other lines from the output. there's bound to be all sorts of horrible failure modes with unexpected input, but it's OK-ish as a quick and dirty hack. – cas Sep 25 at 4:24
  • @ArkadiuszDrabczyk I'd like to avoid sourcing the file, to avoid catastrophic results of evaluating arbitrary bash code. – Charles Langlois Sep 25 at 17:52
  • @cas this could be an ok solution, it seems to work fine. As long as it's strictly better than what I was doing before(which didn't handle spaces in values). – Charles Langlois Sep 25 at 17:57
  • FWIW, set -a; . ./.env; set +a (as in the answer I've deleted because you "don't want to source .env") is much safer than prepending export to each line and then sourcing it. If you want your file to be "simply key-value" then please clearly define its syntax, especially how values containing newlines, quotes, other metacharacters etc are supposed to be represented. – mosvy Sep 25 at 19:26
0

Can you use parset?

parset "`perl -nE '/[^=]+/ && print "$&,"' .env`" echo ::: "`perl -pe 's/[^=]+=//' .env`"

It deals happily with input like:

vv=* ;   & " echo this is a value - not a command

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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