Running Scripts — bash, source, and the PATH
The difference between ./script.sh, bash script.sh, and source — and how to make your scripts available system-wide.
There are multiple ways to run a Bash script, and the difference matters. Using the wrong method can mean your script runs in the wrong environment, or that variables and cd commands inside it don't affect your current shell.
Three Ways to Run a Script
Methods compared
| Method | Subprocess? | Executable bit needed? | Notes |
|---|---|---|---|
./script.sh | Yes | ✅ Yes | Uses shebang interpreter |
bash script.sh | Yes | ❌ No | Forces bash, ignores shebang |
source script.sh | No | ❌ No | Runs in current shell — changes persist |
./script.sh — Run in a Subshell
Running ./script.sh (or /path/to/script.sh) creates a child process (subshell). All commands run in that child process. When the script exits, the child dies — any variables it set or cd commands it ran are gone. Your current terminal is unaffected.
# demo.sh
cd /tmp
MY_VAR="hello"
echo "Inside script: $MY_VAR, PWD=$PWD"echo "Before: PWD=$PWD"
./demo.sh
echo "After: PWD=$PWD, MY_VAR=$MY_VAR"
# PWD is unchanged, MY_VAR is empty — the subshell is gonesource — Run in the Current Shell
source script.sh (also written as . script.sh) does not create a subshell. The commands run directly in your current shell. Variables set and directories changed persist after the script finishes.
This is exactly how ~/.bashrc works — when you open a terminal, your shell sources that file to load your aliases and variables.
source demo.sh # or equivalently: . demo.sh
echo "After source: PWD=$PWD, MY_VAR=$MY_VAR"
# NOW: PWD=/tmp, MY_VAR=hello — changes stuck!When to use source
Use source when a script needs to modify your current shell — like loading environment variables, activating a virtual environment, or defining functions you want to use interactively.
Don't use it for general task scripts — those should run in their own subprocess.
Making Scripts Available System-Wide
You can run a script from anywhere by placing it in a directory that's in your $PATH. ~/bin or ~/.local/bin are standard choices for personal scripts.
# Create ~/bin if it doesn't exist
mkdir -p ~/bin
# Copy or move your script there
cp hello.sh ~/bin/hello
chmod +x ~/bin/hello
# Add ~/bin to PATH in ~/.bashrc (if not already there)
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Now you can run it from anywhere
helloChecking Syntax Without Running
bash -n script.sh # parse and check syntax — does NOT run the script
bash -x script.sh # run with debug output — prints each command before executingUse -n before every commit
bash -n script.sh is a quick sanity check. It catches syntax errors like missing fi, unmatched quotes, and mis-spelled keywords before you run the script for real.
You write a script that sets MY_VAR='hello' and runs `cd /tmp`. After running it with `./script.sh`, what is true?