Reputation: 1961
I am trying to implement a migration script to export some environment variables in bash.
It is more difficult to be explained that to implement.
Basically, there is a set of environment variables and a set of their default values.
A small fragment of the (gigantic) migration script is reported below:
REQUIRED_ENVIRONMENT_VARIABLES=( "BAR" "FOO" "BAZ" )
ENVIRONMENT_VARIABLES_DAFAULT_VALUES=( "/some/path" "0" "true" )
for i in "${!REQUIRED_ENVIRONMENT_VARIABLES[@]}"; do
echo "checking environment variable [$i] ${REQUIRED_ENVIRONMENT_VARIABLES[$i]} which default value is: [${ENVIRONMENT_VARIABLES_DAFAULT_VALUES[$i]}]"
if [[ -z "${REQUIRED_ENVIRONMENT_VARIABLES[$i]}" ]]; then
echo "variable ${REQUIRED_ENVIRONMENT_VARIABLES[$i]} exported with value ${ENVIRONMENT_VARIABLES_DAFAULT_VALUES[$i]}"
echo "export ${REQUIRED_ENVIRONMENT_VARIABLES[$i]}"="${ENVIRONMENT_VARIABLES_DAFAULT_VALUES[$i]}" >> $HOME/.bash_profile
fi
done
Simply, the for loop iterates for each variable into REQUIRED_ENVIRONMENT_VARIABLES
:
export VAR_NAME=DEFAULT_VALUE
into the .bash_profileSo, for example, if the original contents of .bash_profile is:
(.bash_profile)
export FOO=1
export ASD=https://cool.url/
...
after running the migration script, the result should be:
(.bash_profile)
export FOO=1
export ASD=https://cool.url/
...
export BAR=/some/path
export BAZ=true
FOO
remains untouched because already exists.
The problem with this code is that I see no new entries when I try to append it to the .bash_profile using the echo
command. Why?
Upvotes: 0
Views: 452
Reputation: 22225
Wouldn't it be easier to code it like this instead of using an array:
: ${BAR:=/some/path}
: ${FOO:=0}
: ${BAZ:=true}
: ${POOF:=$((FOO+25))} # Default for variable depends on other variable
export FOO BAR BAZ POOF
In this source, the variables would be untouched if they are already set, but get a value if they are not.
Upvotes: 1
Reputation: 125758
The problem is in the test
if [[ -z "${REQUIRED_ENVIRONMENT_VARIABLES[$i]}" ]]; then
This expands out an element of the array, and then checks to see if that array element was the null string (not whether it's the name of a variable). That is, on the first iteration when i=0
, it expands to:
if [[ -z "BAR" ]]; then
...and since "BAR" is not the null string, the test fails. What you want is to treat BAR
as a variable name, rather than a literal string. There are a couple of ways to do this. One is to use a negated -v
test ("is there a variable by this name") (note that this is only available in newer versions of bash):
if [[ ! -v "${REQUIRED_ENVIRONMENT_VARIABLES[$i]}" ]]; then
Another option is to use bash's "indirect" variable expansion feature, by adding a !
at the beginning of the expansion:
if [[ -z "${!REQUIRED_ENVIRONMENT_VARIABLES[$i]}" ]]; then
Note that these aren't quite the same test; the first will treat a variable that's set to the null string as set, the second will not.
BTW, this is a near-duplicate of "How to check if a variable is set in Bash?", but since in this case the variable name is coming from an array, I considered it different enough to treat it as a separate question.
Upvotes: 2