7

I have a file with a large number of variables in it.

$ cat message.txt
Hello, ${LOCATION}! You too, ${PERSON} ;)

If PERSON is not defined, envsubst replaces it with nothing:

$ LOCATION=World envsubst < message.txt
Hello, World! You too,  ;)

How can I make envsubst fail with a non-zero exit code (or something reliable) if any of the many environment variables in the file isn't defined?

6
  • What does it mean to fail? What do you want as a result?
    – golder3
    Feb 2, 2022 at 22:45
  • I would like the equivalent of false, but I guess I could work with anything reliable. I'll edit the question.
    – ixe013
    Feb 3, 2022 at 2:58
  • I don't think the GNU tool has any built-in support for it, but there's this: github.com/a8m/envsubst#imposing-restrictions
    – muru
    Feb 3, 2022 at 3:51
  • envsubst -no-unset is seems that we want, but it is not original GNU gettext implementation, it is new implementation written in Golang. Mar 31, 2022 at 6:39
  • 1
    @muru linked to the github project in their comment.
    – ixe013
    Nov 1, 2022 at 20:11

2 Answers 2

2

This is not ideal, in that it doesn't alter the behaviour of envsubst as requested, but it is able to identify unset variables. The user must ensure that the delimiter EOF does not appear in the text. If it does, then choose a different delimiter.

#!/usr/bin/env bash

msg="$( printf 'cat << EOF\n%s\nEOF\n' "$(cat)" )"

bash -u <<< "$msg"

Output:

$ ./test.sh < message.txt || echo fail
bash: line 1: LOCATION: unbound variable
fail
$ LOCATION=World ./test.sh < message.txt || echo fail
bash: line 1: PERSON: unbound variable
fail
$ LOCATION=World PERSON=Ralph ./test.sh < message.txt || echo fail
Hello, World! You too, Ralph ;)

Here is a lengthier version which will list all the unset variables in one go, instead of disclosing them one at a time:

#!/usr/bin/env bash

check_vars() {

# pass a list of variable names on stdin, one to a line

rc=0

while read v
do
        if [[ ! "${!v}" ]]
        then
                printf '%s\n' "$v"
                rc=1
        fi
done

return $rc

}

envsubst -v "$(cat)" | check_vars

This version will output a list of unset (or null) variables, one to a line, and exit with 0 if and only if the list is empty.

Output:

$ ./test2.sh < message.txt || echo fail
LOCATION
PERSON
fail
$ PERSON=Ralph ./test2.sh < message.txt || echo fail
LOCATION
fail
$ LOCATION=World ./test2.sh < message.txt || echo fail
PERSON
fail
$ LOCATION=World PERSON=Ralph ./test2.sh < message.txt || echo fail
$
2
  • Changing envsubst was not a hard requirement. This simple script reliably detects unset variables, thanks!
    – ixe013
    Dec 2, 2022 at 16:19
  • 1
    You're welcome, @ixe013. I expanded the answer to include a version which lists all the undefined variables, instead of only the first one that is encountered.
    – Jim L.
    Dec 2, 2022 at 21:25
2

You can easily to the equivalent in perl where you can exit with an error if the env var is not defined:

perl -pe 's{\$(?|\{(\w+)\}|(\w+))}{$ENV{$1} // die "$& not defined\n"}ge'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .