I have a .env
file with those vars:
REACT_APP_API_URL=https://my-enpoint.com/api
REACT_APP_APP_URL=https://my-app.com
ESLINT_NO_DEV_ERRORS=true
REACT_APP_PUSHER_APP_KEY=d83519e4-6017-41f4-b8b2-6093f6480914
...etc
I would like to check if any of the variables are missing and print info about missing value in specified variable.
I've tried to read a variables from file in loop but I cannont access to them in loop. Manually its possible, by getting variable one by one. But I want to do it automatically. My code:
VARIABLES=("REACT_APP_URL" "REACT_APP_API_URL" "ESLINT_NO_DEV_ERRORS" "REACT_APP_PUSHER_APP_KEY")
source .env
for i in "${!VARIABLES[@]}"; do
env -S "$(cat .env)" sh -c 'echo '${VARIABLES[$i]}"'
done
I have zero exp in bash but I need to make some basic automation in my project
CodePudding user response:
The code you’ve posted goes in the right direction but it does many incorrect things and hence doesn’t work:
- You don’t need to (and should not)
source
the environment file. - Your code is iterating over the indices of the array
VARIABLES
; why not iterate directly over the values? This simplifies the code. - The
-S
flag ofenv
doesn’t fulfil a purpose here. - Single-quoting the command that we pass to
env
prevents parameter expansion. This means that the command doesn’t actually see the current variable. - Passing the contents of the file as command line arguments to
env
unfortunately won’t work — it will just concatenate all variables into a single line. You can avoid this by not quote the substitution, but then it won’t work if any of the values in the.env
file contains spaces, which is unacceptable.
The last point can probably be solved by some clever trickery involving xargs
but the resulting code is non-portable. It’s much easier to simply source
the file inside the command that’s executed by env
.
Lastly, why are we using env
at all here? Why not just run sh -c
directly? — Because we want to only look at variables that are defined inside .env
. But the code currently doesn’t do that! To do this, we need to pass -i
(or --ignore-environment
) to env
— in other words: ignore the current environment.
Putting all this together:
variables=(REACT_APP_URL REACT_APP_API_URL ESLINT_NO_DEV_ERRORS REACT_APP_PUSHER_APP_KEY)
for var in "${variables[@]}"; do
env -i sh -c "source ./.env; echo \"\$$var\""
done
Some comments:
- By convention,
ALL_CAPS
is reserved for environment variables. We uselowercase
for our non-environment variables. - You don’t need to quote string literals without special characters (i.e. the values of the
variables
array). - We need to pass a path name (
./.env
) tosource
; only using a filename (.env
) does not work, sincesource
then searches the (unset)$PATH
locations. - Don’t forget to quote all expansions! This includes quoting inside the
sh -c
command, hence\"\$$var\"
: the backslashes allow nesting the quotation marks (and escape the initial$
so that the command sees an environment variable name).
This code prints all variables defined in .env
. If you want to instead test whether they’re set, use the following:
for var in "${variables[@]}"; do
env -i sh -c "source ./.env; test -v $var || echo \"$var is unset!\""
done
CodePudding user response:
Something like this may help:
a=1
b=
c=3
vars=(a b c)
for var in ${vars[@]}; {
[[ ${!var} ]] || echo $var is empty
}
Or use grep to check your file:
$ cat env
a=1
b=
c=3
$ vars=$(grep -Ev '(a|b|c)=. ' env)
$ [[ $vars ]] && echo $vars not set
b= not set
To autocheck all vars in env file:
grep -Ev '. =. ' env
b=