0

I am trying to read all the files that end with .env inside the config_files folder and then run the export command to have them available as environment variables.

So far I have tried:

#! /bin/bash
for file in "$(find ~/config_files -maxdepth 3 -name '*.env')"; do export $(grep -v '^#' $file | xargs); done

and

#! /bin/bash
for file in  "$(find ~/config_files -regex '.*/.*\.\(env\)$')"; do export $(xargs < $file); done

Which would always end up having a declare -x issue like:

declare -x COLORTERM="truecolor"

I have also tried adding -print to the bash file like:

for file in "$(find ~/.ros/PS_AD/config_files -maxdepth 3 -name '*.env' -print)"; do export $(grep -v '^#' $file | xargs); done

But then I got:

./script: line 3: export: `/home/imr/config_files/docker-image/docker_specs.env:random=1': not a valid identifier

The *.env files look like:

random=1

What am I missing?

EDIT: Now I am using the proper way ... with IFS and read

find ~/config_files -name '*.env' -print0 |
    while IFS= read -r -d '' line; do
        echo $line
        set -a
        . "$line"
        set +a
    done

but the environment variables are still not set

EDIT: Now also using the pipeline workaround doesn't solve the issue

while IFS= read -r -d ''  p
do
  set -a; . "$p"; set +a
done < <(find ~/config_files -name '*.env' -type f -print0)
ignacio
  • 1,181
  • 2
  • 15
  • 28
  • 2
    Note that when reviewing the answers on the duplicat at https://stackoverflow.com/questions/19331497/set-environment-variables-from-file-of-key-value-pairs, I **strongly** advise ignoring any answer that says a word about xargs, and sticking to those that use `set -a` or `set -o allexport`. – Charles Duffy Feb 10 '23 at 14:28
  • I tried doing what you guys suggested, but it still doesn't work – ignacio Feb 10 '23 at 14:30
  • It works except for the pipeline. Read [BashFAQ #24](https://mywiki.wooledge.org/BashFAQ/024) – Charles Duffy Feb 10 '23 at 15:29
  • Instead of piping from `find` into your loop, use `while ...; done < <(find ~/config_files -name '*.env' -print0)` -- that way the `while` loop, and thus the `env`, runs in your main shell instance, not a subshell, so the variables stay set after the loop has exited. – Charles Duffy Feb 10 '23 at 15:30
  • it still doesn't do the trick. I tried what you suggested and the env variables weren't set. Later, I tried using `mkfifo my_pipe` but then it would get stuck. If I try to run it again it complains that the file `my_pipe` already exists – ignacio Feb 13 '23 at 07:54
  • actually, it works if I run as the script as `source script` – ignacio Feb 13 '23 at 10:30
  • Run `set -x` to enable trace logging while reproducing the failure. And how are you testing whether it worked? If you run the script _as a script_ and then check variables after it exited, _of course_ it won't work, because environment variables don't propagate back to parent processes -- so you need to be checking whether the variables are set _in the same interpreter that exported them_ or a child of that interpreter. – Charles Duffy Feb 13 '23 at 16:05
  • Should that be the problem, then that aspect of the question is a duplicate of [Can a shell script set environment variables of the calling shell?](https://stackoverflow.com/questions/496702/can-a-shell-script-set-environment-variables-of-the-calling-shell) – Charles Duffy Feb 13 '23 at 16:06

1 Answers1

0

You should use while IFS= to 'loop' over the lines, then use export $(xargs < path) to export those to the shell:

$ cat foo/a.env
foo=bar
$
$ find /tmp/foo -type f -print0 | \
    while IFS= read -r -d ''  p; do export $(xargs < $p); done
$
$ echo $foo
bar
$
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • 3
    I'd suggest replacing `export $(xargs < $p)` with `set -a; . "$p"; set +a`, assuming the files are in valid shell syntax (and if they're not, one has bigger problems). An unquoted expansion onto the `export` command line isn't going to behave well when you have values with spaces, values where the unquoting rules xargs follows aren't quite right, etc. (xargs unquoting rules are subtly incompatible with POSIX sh rules -- check behavior of variables with line continuations, f/e). – Charles Duffy Feb 10 '23 at 14:26
  • that works if I run on the terminal, but doesn't work on my bash file – ignacio Feb 10 '23 at 14:59
  • I am using `#!/bin/bash` – ignacio Feb 10 '23 at 14:59
  • this approach had an issue because of the pipeline, as pointed out in [BashFAQ](https://mywiki.wooledge.org/BashFAQ/024) by @Charles Duffy – ignacio Feb 13 '23 at 07:39