DaleSchool

Environment Variables and Configuration

Beginner25min

Learning Objectives

  • Explain the difference between environment variables and local variables
  • Understand the role of the PATH variable and modify it
  • Create shortcuts for frequent commands with aliases and functions
  • Edit the shell config file (.zshrc) for persistent settings

Working Code

Example 1: Checking environment variables

echo $HOME

Example output:

/Users/dale
echo $USER

Output:

dale
echo $PATH

Example output:

/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

PATH is a list of directories separated by : (colons).

Example 2: Setting variables

# Local variable (only valid in the current shell)
MY_NAME="Alice"
echo $MY_NAME

Output:

Alice
# Environment variable (passed to child processes)
export MY_NAME="Alice"
echo $MY_NAME

When you export a variable, other programs launched from this shell can read it too.

Example 3: Viewing all environment variables

env

Output (partial):

HOME=/Users/dale
USER=dale
SHELL=/bin/zsh
PATH=/usr/local/bin:/usr/bin:/bin
LANG=ko_KR.UTF-8
...

You can filter with a pipe: env | grep PATH.

Try It Yourself

Local Variables vs. Environment Variables

# Local variable: current shell only
MY_VAR="hello"
bash -c 'echo $MY_VAR'   # empty in child bash

Output:

                          <- empty (not accessible in child shell)
# Environment variable: passed to child processes
export MY_VAR="hello"
bash -c 'echo $MY_VAR'

Output:

hello

Key difference: variables created without export are only valid in the current shell.

Adding Directories to PATH

# Check current PATH
echo $PATH

# Add a new path at the beginning (higher priority)
export PATH="/new/install/path:$PATH"

# Verify
echo $PATH

If you install a new tool and get "command not found," add its install path to PATH.

alias: Shortening Long Commands

# Create aliases
alias ll='ls -la'
alias gs='git status'
alias ..='cd ..'
alias ...='cd ../..'

# Use them
ll
gs
# List current aliases
alias

# Remove a specific alias
unalias ll

Useful aliases for everyday work:

# Frequently visited directories
alias proj='cd ~/projects'
alias docs='cd ~/Documents'

# Git shortcuts
alias gs='git status'
alias ga='git add .'
alias gc='git commit -m'
alias gp='git push'
alias gl='git log --oneline'

# Better ls
alias ll='ls -la'
alias la='ls -a'
alias lt='ls -lth'    # sort by recent modification

# Safe rm
alias rm='rm -i'      # always ask for confirmation

Persisting Settings in the Shell Config File

Aliases and exports disappear when you close the terminal. To make them permanent, add them to your shell config file:

# zsh users (~/.zshrc)
nano ~/.zshrc

# bash users (~/.bashrc)
nano ~/.bashrc

Add at the bottom:

# Environment variables
export PROJECTS="$HOME/projects"

# Aliases
alias ll='ls -la'
alias gs='git status'
alias ..='cd ..'

# Functions
mkcd() {
  mkdir -p "$1" && cd "$1"
}

Apply the changes:

source ~/.zshrc

Now the settings persist even when you open a new terminal.

"Why?" — Why PATH Matters

PATH is the list of directories the shell searches when you type a command. When you type node, the shell looks through PATH directories in order:

/usr/local/bin -> not found
/usr/bin -> not found
/bin -> found! -> execute

If the command isn't found:

zsh: command not found: node

Run which node to find where node is installed, then add that path to PATH.

Functions: More Complex Logic

For cases too complex for aliases, use functions:

# Create a directory and cd into it
mkcd() {
  mkdir -p "$1" && cd "$1"
}

# Usage
mkcd new-project/src
# Back up a file before editing
backup_edit() {
  cp "$1" "$1.bak" && nano "$1"
}

# Access arguments
greet() {
  echo "Hello, $1!"   # $1 = first argument
  echo "Have a great day."
}
greet "Alice"

Common Mistakes

Mistake 1: Spaces around = in alias

# Wrong (spaces around =)
alias ll = 'ls -la'

# Correct
alias ll='ls -la'

Mistake 2: Forgetting to source

# After editing .zshrc, always apply it
source ~/.zshrc   # or . ~/.zshrc

# Or just open a new terminal

Without source, new settings don't take effect in the current terminal.

Mistake 3: Forgetting export for child processes

# Only valid in the current shell
MYVAR="hello"
npm start   # npm can't read MYVAR

# Now npm can read it
export MYVAR="hello"
npm start

Mistake 4: Committing .env files to git

# .env files contain sensitive data like API keys and passwords
DATABASE_URL=postgresql://...
API_KEY=sk-...

# Never commit these to git!
# Always add to .gitignore
echo ".env" >> .gitignore

Deep Dive

.env files and development environment variables

In development, API keys and DB passwords are stored in .env files:

# .env file
DATABASE_URL=postgresql://localhost/mydb
API_KEY=secret123
NODE_ENV=development

Loading them:

source .env
echo $DATABASE_URL

Most frameworks (Node.js, Python, etc.) read .env automatically. Always add .env to .gitignore.

Finding command locations with which and type
# Where is a command installed?
which node
# /usr/local/bin/node

which python3
# /usr/bin/python3

# Check if something is an alias or function
type ll
# ll is an alias for ls -la

type mkcd
# mkcd is a shell function

When multiple versions are installed, this shows which one runs.

Types of shell config files

| File | When it runs | |------|-------------| | ~/.zshrc | Interactive zsh shell startup | | ~/.bashrc | Interactive bash shell startup | | ~/.zshenv | Every zsh shell (including scripts) | | ~/.bash_profile | Bash login shell startup |

On macOS with zsh, you only need to worry about ~/.zshrc.

  1. Check basic environment variables with echo $HOME, echo $USER, echo $SHELL.
  2. Set a variable with export MYPROJECT="/tmp/test" and verify with echo $MYPROJECT.
  3. Create an alias with alias ll='ls -la' and use it.
  4. Run alias to see all currently defined aliases.
  5. Add 3 useful aliases to ~/.zshrc (or ~/.bashrc) and apply with source.

Q1. How do you make an environment variable available to child processes (npm, python, etc.) as well?

  • A) set VARNAME=value
  • B) export VARNAME=value
  • C) env VARNAME=value
  • D) declare VARNAME=value