-
-
Save mihow/9c7f559807069a03e302605691f85572 to your computer and use it in GitHub Desktop.
# The initial version | |
if [ ! -f .env ] | |
then | |
export $(cat .env | xargs) | |
fi | |
# My favorite from the comments. Thanks @richarddewit & others! | |
set -a && source .env && set +a |
The cleanest solution I found for this was using
allexport
andsource
like thisset -o allexport source .env set +o allexportThis was by far the best solution here for me, removed all the complexity around certain chars, spaces comments etc. Just needed a tweak on formatting to prevent others being tripped up, should be:
set -o allexport source .env set +o allexport
work like a charm. ty
this read line by line, allowing to use previous set variables
while read -r LINE; do if [[ $LINE == *'='* ]] && [[ $LINE != '#'* ]]; then ENV_VAR="$(echo $LINE | envsubst)" eval "declare $ENV_VAR" fi done < .env
this was working the best for me but this still has 2 problems
- code breaks if the value has
()
characters inside it - can not be used inside a function
here is my solution:
read_env() {
local filename="${1:-.env}"
if [ ! -f "$filename" ]; then
echo "missing ${filename} file"
exit 1
fi
echo "reading .env file..."
while read -r LINE; do
if [[ $LINE != '#'* ]] && [[ $LINE == *'='* ]]; then
export "$LINE"
fi
done < "$filename"
}
UPDATED VERSION BELOW
Hi, here is mine solution to read vars from /etc/environemnt
file which I used in /etc/profile
or /etc/bash.bashrc
oneliner for easier validation if line exists in file
(I removed single quotes '
from conditions, so it could be easier parsed by grep)
while read -r LINE; do [[ ${LINE} =~ ^# || ${LINE} =~ ^PATH= || ! ${LINE} == *=* || ${LINE} =~ ^[0-9] || ${LINE} =~ ^[^a-zA-Z_] ]] || export "${LINE}"; done < "/etc/environment"
or formatad syntax:
while read -r LINE; do
if [[ ${LINE} =~ ^# || ${LINE} =~ ^PATH= || ! ${LINE} == *=* || ${LINE} =~ ^[0-9] || ${LINE} =~ ^[^a-zA-Z_] ]]; then
continue
else
export "${LINE}"
fi
done < "/etc/environment"
Hi,
Here is my solution to read vars from .env file and ignoring #
and cleaning values from '
and "
.
https://gist.github.com/shadiabuhilal/220aa09f9bb83caed93a1f87401fcc60
dot-env.sh
File:
#!/bin/bash
# Specify the path to your .env file
ENV_FILE=".env"
# Check if the .env file exists
if [ -f "$ENV_FILE" ]; then
echo "[INFO]: Reading $ENV_FILE file."
# Read the .env file line by line
while IFS= read -r line; do
# Skip comments and empty lines
if [[ "$line" =~ ^\s*#.*$ || -z "$line" ]]; then
continue
fi
# Split the line into key and value
key=$(echo "$line" | cut -d '=' -f 1)
value=$(echo "$line" | cut -d '=' -f 2-)
# Remove single quotes, double quotes, and leading/trailing spaces from the value
value=$(echo "$value" | sed -e "s/^'//" -e "s/'$//" -e 's/^"//' -e 's/"$//' -e 's/^[ \t]*//;s/[ \t]*$//')
# Export the key and value as environment variables
export "$key=$value"
done < "$ENV_FILE"
echo "[DONE]: Reading $ENV_FILE file."
else
echo "[ERROR]: $ENV_FILE not found."
fi
Enjoy :)
Thanks!
One-liner while running command a script (such as pnpm script)
I added parentheses not to pollute global environment vars. Not sure if it's needed though.
(export $(cat .env | xargs) && pnpm compile)
this is the final version that im using, seems to work for all situations
read_env() {
local filePath="${1:-.env}"
if [ ! -f "$filePath" ]; then
echo "missing ${filePath}"
exit 1
fi
echo "Reading $filePath"
while read -r LINE; do
# Remove leading and trailing whitespaces, and carriage return
CLEANED_LINE=$(echo "$LINE" | awk '{$1=$1};1' | tr -d '\r')
if [[ $CLEANED_LINE != '#'* ]] && [[ $CLEANED_LINE == *'='* ]]; then
export "$CLEANED_LINE"
fi
done < "$filePath"
}
Thanks @MansourM !
this is the final version that im using, seems to work for all situations
read_env() { local filePath="${1:-.env}" if [ ! -f "$filePath" ]; then echo "missing ${filePath}" exit 1 fi log "Reading $filePath" while read -r LINE; do # Remove leading and trailing whitespaces, and carriage return CLEANED_LINE=$(echo "$LINE" | awk '{$1=$1};1' | tr -d '\r') if [[ $CLEANED_LINE != '#'* ]] && [[ $CLEANED_LINE == *'='* ]]; then export "$CLEANED_LINE" fi done < "$filePath" }
Looks great, but it doesn't work if the .env file contains only 1 row (just one without br)
Looks great, but it doesn't work if the .env file contains only 1 row (just one without br)
how do you use it?
you get any errors?
btw u need to comment or remove this line as you don't have the log function
log "Reading $filePath"
I needed this and after reading the above realized none of the solutions quite worked for my .env file on a Mac... so I modified what @shadiabuhilal into this (which I put into a file called "readenv")
# quick bash function to read .env file
# use it via:
# source readenv
# readenv
#
# or
#
# readenv <filename>
#
# modified from https://gist.github.com/mihow/9c7f559807069a03e302605691f85572
# fixed for whitespace issues, posix compliance (e.g. \t on mac means t)
#
# NOT a standalone script as when used as a standalone script, it'll read in the ENV variables into a sub-process, not the
# calling process
readenv() {
local filePath="${1:-.env}"
if [ ! -f "$filePath" ]; then
# silently be done
# put some error / echo if you prefer non-silent errors
return 0
fi
# echo "Reading $filePath"
while read -r line; do
if [[ "$line" =~ ^\s*#.*$ || -z "$line" ]]; then
continue
fi
# Split the line into key and value. Trim whitespace on either side.
key=$(echo "$line" | cut -d '=' -f 1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
value=$(echo "$line" | cut -d '=' -f 2- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
# Leaving the below here... normally this works, but if you have something like
# FOO=" string with leading and trailing "
# then the leading / trailing spaces are deleted. FOO="a word", FOO='a word', and FOO=a word all generally work
# so leave the quotes
# Remove single quotes, double quotes, and leading/trailing spaces from the value
# value=$(echo "$value" | sed -e "s/^'//" -e "s/'$//" -e 's/^"//' -e 's/"$//' -e 's/^[[:space:]]*//;s/[[:space:]]*$//')
# Export the key and value as environment variables
# echo "$key=$value"
export "$key=$value"
done < "$filePath"
}
Also - recommend to use [[:space:]] rather than \s or [ \t] --- on Macs, \s isn't space, and \t isn't TAB but t. Yay standardization!
This is what I use:
# shellcheck disable=SC2046
[ -f .env ] && export $(grep -v '^#' .env | xargs)
No need to do a double negation with [ ! -f .env ] ||
when you can do [ -f .env ] &&
@bfontaine thanks, worked like a charm.
Although
set -a; source .env; set +a
is elegant and short, one feature which I missed is this overwrite existing exported variables.I my use case I have a script, which connects to postgres with a predefined user. This user is stored in
.env
file asPG_USER=myuser
. So the script does the magicalset -a; source .env; set +a
and everything works. But sometimes I need ad-hoc change the user. So what I'd do isPG_USER=postgres ./my_script.sh
. In order not to over write the existing var I did this horrendous piece of code: