When I try to run a script that contains the envsubst command, I get this error. Looking online, this seems to be a standard bash command, so I am not sure what to install in order to get it to work.
-
4`envsubst` is included in `gettext` package. you may compile by your own. see http://stackoverflow.com/questions/14940383/how-to-install-gettext-on-macos-x – ymonad May 13 '14 at 00:13
-
I posted it as answer. – ymonad May 13 '14 at 03:45
6 Answers
brew install gettext
brew link --force gettext
This will enable envsubst on OS X, and force it to link properly. It requires homebrew to be installed.

- 5,598
- 2
- 25
- 22
-
1`Linking /usr/local/Cellar/gettext/0.19.8.1... 194 symlinks created` ... wtf 194 symlinks? – Alexander Mills Jun 03 '19 at 21:12
-
@AlexanderMills yeah `gettext` includes a hell of a lot of stuff; it seems like overkill just to get `envsubst` installed but it's the quickest and simplest way. – cobberboy Jun 05 '19 at 02:10
-
seems like they're symlinking every file instead of just symlinking a folder – Alexander Mills Jun 05 '19 at 03:31
-
1@AlexanderMills Yes, this is how Homebrew works: it symlinks each executable into `/usr/bin`. There's not really a good way to symlink a single directory there and have each executable be available on the shell PATH. – Peeja Jan 11 '22 at 19:40
Edit: @cobberboy 's anwer is more correct. upvote him.
brew install gettext
brew link --force gettext
Following is my old answer:
envsubst
is included in gettext
package.
Therefore you may compile it by your own, using standard build tools such as make
or using homebrew
.
However, it seems to have little issue when installing gettext
in MacOS.
See following url for details: How to install gettext on MacOS X

- 11,710
- 1
- 38
- 49
-
8While `envsubst` is part of gettext (as installed by homebrew) it is not linked by default. I expect this is because gettext is a keg-only formula. You could tell homebrew to link the keg, but this might have unintended side-effects. A less intrusive approach is to setup an alias by adding `alias envsubst='/usr/local/Cellar/gettext/0.19.6/bin/envsubst'` to your `.profile` (or equivalent). Of course, you may have another version of gettext installed. You can learn about it by running `brew info gettext`. – trkoch Nov 10 '15 at 18:30
-
2@trkoch You probably want to alias `/usr/local/opt/gettext/bin/envsubst` which survives upgrades – Christoph Hösler Dec 20 '17 at 17:40
-
1While this is the accepted answer, please scroll down to @cobberboy's answer, as it is also a common probably that you need to force the link. – Big Money Jun 08 '18 at 23:00
-
I wondered why I was suddenly getting more upvotes. Thanks for your generosity @ymonad – cobberboy Dec 03 '18 at 12:28
-
1Linking /usr/local/Cellar/gettext/0.19.8.1... 194 symlinks created ... wtf 194 symlinks? – Alexander Mills Jun 03 '19 at 21:12
To clear up potential confusion:
envsubst
is an external executable and thus not part of Bash; external executables are platform-dependent, both in terms of which ones are available as well as their specific behavior and the specific options they support (though, hopefully, there is a common subset based on the POSIX specifications)- Commands directly built into
bash
are called builtins, and only they can be relied upon to be present on all platforms.
To test whether a given command is a builtin, use
type <cmdName>
In the case at hand, running type envsubst
on macOS 10.13 returns -bash: type: envsubst: not found
, from which you can infer:
envsubst
is NOT a builtinenvsubst
is not in your system's$PATH
(and thus likely not present on your system)
(By contrast, running the same on command on, e.g., a Ubuntu 12.04 system returns envsubst is hashed (/usr/bin/envsubst)
, which tells you that the utility is present and where it is located.)
A makeshift alternative to envsubst
is to use eval
, although the usual caveat applies: use eval
only on strings whose content you control or trust:
Assume a sample.txt
file containing text with unexpanded variable references; e.g.:
cat > sample.txt <<'EOF'
Honey, I'm $USER
and I'm $HOME.
EOF
The equivalent of:
envsubst < sample.txt
is:
eval "echo \"$(sed 's/"/\\"/g' sample.txt)\""
There is a crucial difference, however:
envsubst
expands only environment variable references- whereas
eval
will expand shell variable references too - as well as embedded command substitutions, which is what makes use ofeval
a security concern.

- 382,024
- 64
- 607
- 775
-
I like the idea of `eval echo` because I trust the source but it's not the same.. `envsubst < .env.example` can not just be `eval echo < .env.example` – iRaS Oct 20 '17 at 09:53
I'm using this now in my bash script that requires envsubst:
if ! which envsubst > /dev/null 2>&1; then
envsubst() {
while read line; do
line=$( echo $line | sed 's/"/\\"/g' )
eval echo $line
done
}
fi
you can use it as the envsubst command - of course it's not feature complete or something else:
envsubst <<<'Honey, I am $HOME.'
envsubst < input > output 2> corrupt

- 1,958
- 1
- 16
- 29
-
-
as said this is a workaround that is not feature complete. you could try adding `"` around $line but I did not try this yet – iRaS Jul 20 '18 at 06:08
-
This approach seems to handle whitespace properly and is faster: `sed 's/"/\\"/g' | eval "echo \"$(cat -)\""` – Evan Owen Dec 12 '22 at 18:46
-
@EvanOwen nice. does that replace the whole while loop? it looks like it... I would like to update the answer then. – iRaS Dec 14 '22 at 15:30
If you don't want to bother installing homebrew and gettext, a one line perl executable will do:
#!/usr/bin/perl -p
$_ =~ s/\Q${$1||$2}/$ENV{$1?$2:$4}/ while $_ =~ /(\$\{([^}]+)})|(\$(\w+))/g;

- 884
- 1
- 8
- 16
If you don't want to bother installing homebrew and gettext, and can't make heads or tails of perl, a simple python script also does the trick:
envsubst() {
python -c 'import os,sys;[sys.stdout.write(os.path.expandvars(l)) for l in sys.stdin]'
}
The advantage of this over eval
solutions is that it only handles variable replacement and won't execute arbitrary scripts like eval
does.
$ cat > sample.txt <<'EOF'
Honey, I'm $USER
and I'm $HOME.
Danger: $( echo 'eval can do evil here, but python expandvars rocks' )
EOF
$ envsubst < sample.txt
Honey, I'm mattmc3
and I'm /Users/mattmc3.
Danger: $( echo 'eval can do evil here, but python expandvars rocks' )

- 17,595
- 7
- 83
- 103