Skip to content

Instantly share code, notes, and snippets.

Last active April 23, 2024 22:07
Show Gist options
  • Save mihow/9c7f559807069a03e302605691f85572 to your computer and use it in GitHub Desktop.
Save mihow/9c7f559807069a03e302605691f85572 to your computer and use it in GitHub Desktop.
Load environment variables from dotenv / .env file in Bash
if [ ! -f .env ]
export $(cat .env | xargs)
Copy link

ddosia commented Aug 2, 2023

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 as PG_USER=myuser. So the script does the magical set -a; source .env; set +a and everything works. But sometimes I need ad-hoc change the user. So what I'd do is PG_USER=postgres ./ In order not to over write the existing var I did this horrendous piece of code:

for l in $(cat /etc/my_service/.env); do
    IFS='=' read -ra VARVAL <<< "$l"
    # If variable with such name already exists, preserves it's value
    eval "export ${VARVAL[0]}=\${${VARVAL[0]}:-${VARVAL[1]}}"
unset IFS

Copy link

The cleanest solution I found for this was using allexport and source like this

set -o allexport
source .env set
+o allexport

This 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

Copy link

MansourM commented Nov 24, 2023

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"
  done < .env

this was working the best for me but this still has 2 problems

  1. code breaks if the value has () characters inside it
  2. 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

  echo "reading .env file..."
  while read -r LINE; do
    if [[ $LINE != '#'* ]] && [[ $LINE == *'='* ]]; then
      export "$LINE"
  done < "$filename"


Copy link

emilwojcik93 commented Jan 7, 2024

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
    export "${LINE}"
done < "/etc/environment"

Copy link

shadiabuhilal commented Feb 2, 2024


Here is my solution to read vars from .env file and ignoring # and cleaning values from ' and ". File:


# Specify the path to your .env file

# 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

    # 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."
  echo "[ERROR]: $ENV_FILE not found."

Enjoy :)

Copy link

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)

Copy link

rrakso commented Feb 28, 2024

source .env

works for me

wont work if you have # in your .env

@abhidp it seems, that it works well - even with comments in .env! :D (cc: @muthugit)

Copy link

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

  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"
  done < "$filePath"

Copy link

Thanks @MansourM !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment