'npm tells .env file doesn't exist (but it does), and it can even print it
All I want is to simply use an environment variable in an npm script without installing unnecessary dependencies.
I have a .env
file in the project root, containing
AWS_S3_BUCKET_ID=whatever
My package.json
includes these scripts
"scripts": {
"grep": "echo $(grep AWS_S3_BUCKET_ID .env | cut -d '=' -f2)",
"source": "source .env && echo $AWS_S3_BUCKET_ID",
"test-source": "[ -f .env ] && cat .env && npm run source"
},
Believe it or not, npm run grep
executes, while npm run source
does not.
Now, the absurdity is that npm run source
returns with the following error message
sh: line 0: source: .env: file not found
and npm run test-source
first prints the file content (!!) and then says the file does not exist.
Is there a reason for this behaviour?
edit: I'm on Linux
Solution 1:[1]
Try this:
...
"source": ". ./.env && echo $AWS_S3_BUCKET_ID",
...
I couldn't get the source command to work at all in Ubuntu under an npm script (sh: 1: source: not found), but this worked for me with a minimal project set up like yours.
Noted in this answer: https://stackoverflow.com/a/670209/4068418
In the POSIX standard, which /bin/sh is supposed to respect, the command is . (a single dot), not source. The source command is a csh-ism that has been pulled into bash.
You can also use the env-cmd package from npm to be cross platform, but it seems you're okay with making your scripts Linux only.
Solution 2:[2]
It looks like this has to do with the fact that npm-run
uses /bin/sh
by default to run scripts rather than /bin/bash
.
This may come as a surprise because on the /bin/sh
dot command, the filename is relative to the $PATH
and doesn't include the current working directory. You can actually test it through:
$ sh
sh-5.1$ . .env
sh: .: .env: file not found
sh-5.1$
This is the reason you need to make sure the relative path is explicitly mentioned as . ./.env
.
However, on /bin/bash
the dot command (.
) is an alias to source, which behaves differently and includes the current working directory as part of the file lookup, so both the below commands are synonyms and work "as you would expect"
$ /bin/bash
$ . .env
$ source .env
To work around this, you can, as @wowyesokay mentioned, simply use the relative file path, or run the NPM scripts with the flag script-shell
flag. As npm run test-source --script-shell /bin/bash
. Alternatively, you may want to add that option to your .npmrc
file, so all calls use script-shell as bash.
On this page you can find some valuable explanation about the dot command on /bin/sh
, most notably, this part:
If there are slashes in the file name, . (dot) looks for the named file. If there are no slashes . (dot) searches for file in the directories specified in the PATH variable. This may surprise some people when they use dot to run a file in the working directory, but their search rules are not set up to look at the working directory. As a result, the shell does not find the shell file.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | zanona |