Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Please just see this

`env -S "$(cat .env)" <cmd>`

Believe it or not that’s all you need.

> S, --split-string=S process and split S into separate arguments; used to pass multiple arguments on shebang lines

edit: forgot the quotes around shell substitution



Also, if we are going to involve the shell, we could also just make .env a shell fragment and do this:

   sh -c '. .env; <cmd>'
There is a way to pass commands to it which are reliably executed, like thisL

   sh -c '. .env; "$@"' -- command arg1 arg2 arg3.
The non-option arguments passed to the shell are available as `"$@"`. A command consisting of nothing but `"$@"` basically executes the arguments. We can use `exec`, speaking of which:

   sh -c '. .env; exec "$@"' -- command arg1 arg2 arg3.
What I'm getting at is that this form is fairly easily exec-able;

   execl("/bin/sh", "/bin/sh", ". .env; exec \"$@\"", "--", "command",
         "arg1", "arg2", "arg3", (char *) 0);
The command and arguments can be arbitrary strings, not subject to any shell mangling.


I wouldn't follow this approach because if you run `. .env;` you .env gets evaluated as a bash script, not as a configuration file. This means that you can get runtime errors in the .env file, and nobody wants that.


Sourced environment scripts in the Unix environment are standard operating procedure. E.g. for toolchains.

The .env being evaluated as a shell script means that it's in a widely used language, with a widely known syntax. You can look at it and know what it's going to do.

The .env being a data format to some uncommon utility; that's anyone's guess.

For instance, suppose we want a newline character in an environment variable. Does the given "env file" format support that? How?

There is one de-facto standard format: the /proc/<pid>/environ kernel output format on Linux. The variables are null-terminated strings, so it is effectively a binary format. It represents any variable value without requiring quoting mechanisms.


This is now syntax that requires processing by the shell.

The nice thing about utilities like env and dotenv is that they can be easily exec-ed:

  execl("/usr/bin/dotenv", "/usr/bin/dotenv", "command", "arg", (char *) 0);
-S is a fairly recently added option to the GNU Coreutils env (possibly inspired by BSD?). I have a window to an Ubuntu 18 VM where it's not available.

You want $(cat .env) quoted, as in "$(cat .env)" so that the content of the file is reliably passed as one argument.

-S will split on whitespace; but it respects quoting, so spaces can be protected. Basically .env has to be prepared with the features of -S in mind. Of which that thing has quite a few: escape sequences like \n, commenting, environment variable substitution.


This will fail with comments. Of course you can script around that as well (I have done so), but it's not bulletproof. It makes sense to have a dedicated tool for the job.


Isn’t the problem with dotenv that it’s not a formal specification? The closest to a specification is the “reference” nodejs implementation. Even across languages that aren’t shell the behaviors differ to some extent. I think also it’s not just comments, there are probably some other edge cases that can’t be parsed as legitimate shell code either.


ksh/bash can abbreviate $(cat x) to $(<x) although this syntax is not in POSIX (and it should be).


What is the difference with or without "-S". 'env $(cat .env) <cmd>' still work?


edit 2: seems that there are expectation around a complex .env unspecified file format I was totally not aware of, I was just merely trying to share the simplest way I've ever found to store and reuse env vars




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: