Shell builtins · bash builtin
source
Run the commands in a file inside the current shell, so its variables, functions and directory changes stay in effect.
source FILENAME [ARGUMENT...] or . FILENAME [ARGUMENT...]
Running a script normally (./script.sh or bash script.sh) starts a new process. Whatever
it sets, variables, functions, cd, set options, disappears when that process exits.
source file instead reads the file and executes it in the current shell, as if you had
typed its lines. That is how ~/.bashrc is loaded, how a script pulls in a library of
functions, and how a virtualenv's activate changes your prompt.
. (a single dot) is the POSIX name for the same command; source is a bash spelling that
dash does not have. If the file name contains no slash, both search PATH before the current
directory, which is rarely what you want, so write ./file or a full path.
Sourcing has no isolation: a sourced file that calls exit exits your shell, and one that
runs set -e changes it for the rest of your session. To stop early from a sourced file, use
return. Only source files you trust, since they run with all of your shell's permissions
and variables.
Examples
Load variables from a file into the current shell
APP_NAME=demo
APP_PORT=8080
source ./app.env
echo "$APP_NAME listens on $APP_PORT"
demo listens on 8080
The assignments in app.env run in the current shell, so the variables exist after the
source line. Any file of NAME=value lines in shell syntax can be loaded this way.
Sourcing versus running a script
cd /tmp
GREETING=hello
bash setdir.sh
echo "after bash: pwd=$PWD greeting=[$GREETING]"
source ./setdir.sh
echo "after source: pwd=$PWD greeting=[$GREETING]"
after bash: pwd=/home/dev/demo greeting=[] after source: pwd=/tmp greeting=[hello]
bash setdir.sh runs in a child process; its cd and variable vanish with it. Sourced,
the same lines change the current shell. This is why a script cannot cd for you unless
you source it.
Use functions from a library file
source src/util.sh
log "starting backup"
type die | head -n 3
20:20:57 starting backup
die is a function
die ()
{ src/util.sh defines log and die. After sourcing it they are ordinary functions in
this shell. log writes a timestamped line to stderr. Scripts usually locate the library
relative to themselves with source "$(dirname "$0")/util.sh".
The portable form is a dot
. ./.env
echo "API_URL is $API_URL"
source ./.env
API_URL is http://localhost:8080 /bin/sh: 3: source: not found
Under dash, /bin/sh on Debian and Ubuntu, . works and source is not a command.
Use . in any script with a #!/bin/sh line.
A name without a slash is looked up in PATH
echo "loaded settings.sh from the current directory"
. settings.sh
echo "status: $?"
. ./settings.sh
loaded settings.sh from the current directory status: 0 loaded settings.sh from the current directory
bash searches PATH first and then falls back to the current directory, so this works
here, but if a settings.sh existed anywhere in PATH, that one would run instead.
In dash and in bash's POSIX mode there is no fallback at all. Writing ./settings.sh avoids both
surprises.
Export everything a file sets with set -a
set -a
source ./.env
set +a
env | grep -E '^(API_URL|DEBUG)='
API_URL=http://localhost:8080 DEBUG=false
Variables set by sourcing are shell variables, invisible to child processes. set -a
marks every assignment for export while it is on, so env (a child process) sees both
values from .env. A common way to load dotenv files.
Pass arguments to a sourced file
echo "sourced with $# args: $*"
set -- outer1 outer2
source ./show-args.sh one two three
source ./show-args.sh
sourced with 3 args: one two three sourced with 2 args: outer1 outer2
Extra words after the file name become $1, $2, ... while the file runs. Without them,
the file sees the caller's positional parameters, here outer1 outer2.
Stop a sourced file early with return
if [ -z "${API_URL:-}" ]; then
echo "guard: API_URL not set, skipping the rest"
return 1
fi
echo "guard: using $API_URL"
source ./guard.sh; echo "status $?, shell still running"
API_URL=http://localhost:8080 source ./guard.sh
guard: API_URL not set, skipping the rest status 1, shell still running guard: using http://localhost:8080
return ends the sourced file and gives source its status, leaving the shell running.
An exit in the same place would have ended the calling shell, or closed your terminal
if you sourced it interactively.
Sourcing a missing file
source ./no-such-file.sh
echo "status: $?"
/bin/bash: line 1: ./no-such-file.sh: No such file or directory status: 1
bash prints an error and source returns 1, but the shell continues. Check with [ -r
file ] first when the file is optional, or let set -e stop a script that requires it.
Common pitfalls
Calling
exitin a file meant to be sourced kills the caller's shell (or your terminal). Usereturn.source filewithout a slash searches PATH first. Writesource ./fileor an absolute path.sourcedoes not exist in dash, so#!/bin/shscripts that use it fail withsource: not found. Use..Sourcing a
.envfile written for Docker or a dotenv library: values with spaces or$need shell quoting there, and an unquoted value with a space runs the rest as a command.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
.is POSIX and works in every Bourne-style shell;sourceexists in bash, zsh and ksh but not dash. On macOS/bin/shis normally bash in POSIX mode, wheresourcehappens to work, so a script can pass there and fail on Debian.
Related
execReplace the shell with another program, or, with only redirections, change where the shell's own input and output go.exportMark shell variables (or bash functions) to be passed to every program the shell starts.setTurn shell options such as -e, -u, -x and pipefail on or off, and replace the positional parameters.envPrint the environment, or run a command with a modified environment.- Running scriptsThe four ways to start a script (./script, bash script, PATH, source), what each one changes, and the errors you get when one goes wrong.
- FunctionsDefining and calling bash functions, arguments, local variables, return status versus output, namerefs, and sourcing a function library.
- Environment variablesHow export passes variables to child processes, the one-command NAME=value prefix, loading .env files, and why a child cannot change its parent.
- Subshells and command groupingThe difference between ( ... ) and { ...; }, what a subshell inherits and what it cannot change, which constructs create one, and what that costs.