A
cd ..
Tools

Source & Dot Command

Execute scripts in current shell with source and dot (.) commands.

2025-12-06
source, dot, shell, bash

Source vs execution

# Execute in subshell (doesn't affect current shell)
./script.sh
bash script.sh

# Execute in current shell (affects current shell)
source script.sh
. script.sh

Basic usage

# Both are equivalent
source ~/.bashrc
. ~/.bashrc

# Source with arguments
source script.sh arg1 arg2
. script.sh arg1 arg2

Common use cases

Reload shell configuration

# After editing ~/.bashrc
source ~/.bashrc

# Or with dot
. ~/.bashrc

# Zsh
source ~/.zshrc

Load environment variables

# Load .env file
source .env
. .env

# Load with export
set -a
source .env
set +a

Apply aliases/functions

# ~/.bash_aliases
alias ll='ls -lah'
alias gs='git status'

# Load
source ~/.bash_aliases

Difference from execution

Execution (./script.sh)

# script.sh
export VAR=value
cd /tmp

# Run
./script.sh
echo $VAR      # Empty (subshell)
pwd            # Original directory

Source (source script.sh)

# script.sh
export VAR=value
cd /tmp

# Run
source script.sh
echo $VAR      # Shows 'value'
pwd            # Shows /tmp

Return vs exit

# In sourced script
return 0  # Safe in sourced script
exit 0    # Exits shell! Dangerous when sourced

Safe script

#!/bin/bash

# Check if sourced
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
    # Executed directly
    exit_cmd="exit"
else
    # Being sourced
    exit_cmd="return"
fi

# Later in script
$exit_cmd 0  # Safe in both cases

Load configuration files

User profile

# Login shells read (in order):
# /etc/profile
# ~/.bash_profile or ~/.bash_login or ~/.profile

# Interactive shells read:
# ~/.bashrc

# Force reload all
source /etc/profile
source ~/.bash_profile
source ~/.bashrc

Project configuration

#!/bin/bash
# project-setup.sh

export PROJECT_ROOT=/path/to/project
export PATH=$PROJECT_ROOT/bin:$PATH
alias build='make -C $PROJECT_ROOT'
cd $PROJECT_ROOT

# Usage:
# source project-setup.sh

Conditional sourcing

# Only if file exists
[ -f ~/.bash_custom ] && source ~/.bash_custom

# Or with test
if [ -f ~/.bash_aliases ]; then
    source ~/.bash_aliases
fi

# Multiple files
for file in ~/.bash_*; do
    [ -f "$file" ] && source "$file"
done

Source in scripts

#!/bin/bash

# Load configuration
source /etc/myapp/config.sh

# Load  functions
source ./lib/functions.sh

# Use loaded config
echo "Database: $DB_HOST"

# Use loaded functions
my_function arg1 arg2

Virtual environments

Python

# Activate venv
source venv/bin/activate

# Or
. venv/bin/activate

# Deactivate (function loaded by activate)
deactivate

Node.js (nvm)

# Load nvm
source ~/.nvm/nvm.sh

# Use
nvm use 16

Function libraries

# lib/functions.sh
log_info() {
    echo "[INFO] $*"
}

log_error() {
    echo "[ERROR] $*" >&2
}

# Usage in script
source lib/functions.sh
log_info "Starting process"
log_error "Something went wrong"

Configuration management

# config/development.sh
export DB_HOST=localhost
export DB_PORT=5432
export DEBUG=true

# config/production.sh
export DB_HOST=prod-db.example.com
export DB_PORT=5432
export DEBUG=false

# Load based on environment
ENV=${1:-development}
source "config/${ENV}.sh"

Error handling

# Exit if source fails
source config.sh || exit 1

# With message
source config.sh || {
    echo "Failed to load config"
    exit 1
}

# Continue on error
source optional-config.sh 2>/dev/null || true

Security considerations

# Always validate before sourcing
CONFIG_FILE="$1"

# Check exists
[ -f "$CONFIG_FILE" ] || {
    echo "Config file not found"
    exit 1
}

# Check ownership
[ "$(stat -c %U "$CONFIG_FILE")" = "root" ] || {
    echo "Config must be owned by root"
    exit 1
}

# Check permissions
[ "$(stat -c %a "$CONFIG_FILE")" = "600" ] || {
    echo "Config must be 600"
    exit 1
}

# Then source
source "$CONFIG_FILE"

Common patterns

Load all configs

# Load all .sh files in directory
for config in /etc/myapp/*.sh; do
    [ -f "$config" ] && source "$config"
done

Cascade configuration

# Load in order (later override earlier)
source /etc/app/defaults.sh
source /etc/app/config.sh
source ~/.apprc
source ./.app-local

Profile snippets

# ~/.bashrc
if [ -d ~/.bashrc.d ]; then
    for rc in ~/.bashrc.d/*.sh; do
        [ -f "$rc" ] && . "$rc"
    done
fi
unset rc

Troubleshooting

Variable not set

# Check if file was actually sourced
source script.sh
echo $?  # 0 = success

# Debug
set -x
source script.sh
set +x

Path issues

# Use absolute path
source /absolute/path/to/script.sh

# Or relative to script location
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$DIR/lib/functions.sh"

Already sourced check

# In script
if [ -n "$MYLIB_LOADED" ]; then
    return
fi
export MYLIB_LOADED=1

# Rest of script...

Best practices

# 1. Use source for configuration
source ~/.bashrc
source .env

# 2. Use execution for actions
./build.sh
bash deploy.sh

# 3. Check before sourcing
[ -f config.sh ] && source config.sh

# 4. Use absolute paths in scripts
source "$(dirname "$0")/lib/functions.sh"

# 5. Document what's loaded
# Load database configuration
source config/database.sh

# 6. Handle errors
source critical-config.sh || exit 1
source optional-config.sh || true

Quick reference

# Basic usage
source file.sh
. file.sh

# Common files
source ~/.bashrc          # Reload bash config
source ~/.bash_aliases    # Load aliases
source .env              # Load environment
source venv/bin/activate # Python venv

# Conditional  
[ -f file.sh ] && source file.sh

# With error handling
source file.sh || exit 1

# Check if sourced
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
    echo "Script is being sourced"
fi

Was this useful?

Share with your team

Browse More