directory
script
bash

How do I get the directory where a Bash script is located from within the script itself?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Bash, the usual way to get the directory of the current script is to start from BASH_SOURCE[0], take its directory name, change into that directory, and print the absolute path. This matters when a script needs to find files relative to its own location instead of relative to the caller's current working directory. The common one-liner is short, but understanding why it works helps you avoid subtle path bugs.

The Common Bash Pattern

bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

This assigns the absolute directory of the current script to SCRIPT_DIR.

You can then use it to reference sibling files safely.

bash
CONFIG_FILE="$SCRIPT_DIR/config.env"
echo "$CONFIG_FILE"

That works even if the user runs the script from some completely different directory.

Why BASH_SOURCE[0] Is Better Than $0

A lot of older snippets use $0. That can work in simple cases, but BASH_SOURCE[0] is usually the better Bash-specific choice because it refers to the script file currently being executed, including sourced files.

bash
echo "BASH_SOURCE[0]=${BASH_SOURCE[0]}"
echo "0=$0"

The two values are not always the same. If the script is sourced or wrapped in another invocation style, $0 can describe the shell or entry command rather than the actual file you want.

That is why BASH_SOURCE[0] is the standard Bash answer.

Why the cd and pwd Matter

dirname only extracts the directory portion of a path. It does not guarantee an absolute path.

For example, if the script is invoked with a relative path such as ./scripts/run.sh, then:

bash
dirname "${BASH_SOURCE[0]}"

may give a relative directory such as ./scripts.

The nested cd plus pwd turns that into a stable absolute path:

bash
cd "$(dirname "${BASH_SOURCE[0]}")" && pwd

That is why the full one-liner is more robust than using dirname alone.

A Complete Example

bash
1#!/usr/bin/env bash
2set -euo pipefail
3
4SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5DATA_DIR="$SCRIPT_DIR/data"
6
7printf 'Script directory: %s\n' "$SCRIPT_DIR"
8printf 'Data directory: %s\n' "$DATA_DIR"

This script will produce the correct directory paths regardless of where the caller runs it from.

The basic pattern gives you the directory of the script path Bash used. If the script itself is a symbolic link, resolving the final physical target path requires extra work.

A common extension is:

bash
1SOURCE="${BASH_SOURCE[0]}"
2while [ -L "$SOURCE" ]; do
3  DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
4  SOURCE="$(readlink "$SOURCE")"
5  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
6done
7SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"

You only need this if symlink resolution matters for your script design.

Use Paths Relative to the Script, Not the Caller

The real purpose of SCRIPT_DIR is not just printing it. The point is to anchor resource paths to the script location.

Good:

bash
source "$SCRIPT_DIR/lib/helpers.sh"

Risky:

bash
source ./lib/helpers.sh

The second form depends on the caller's current directory, which makes the script fragile.

Common Pitfalls

The most common mistake is using $0 and assuming it always names the actual script file. In Bash, BASH_SOURCE[0] is usually the safer answer.

Another issue is using dirname alone and forgetting that it may return a relative path.

Developers also sometimes expect the basic pattern to resolve symlinks fully. It does not unless you add explicit symlink handling.

Finally, keep in mind that this is a Bash solution. If the script is meant for plain POSIX sh, BASH_SOURCE is not available.

Summary

  • The usual Bash solution is SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)".
  • 'BASH_SOURCE[0] is generally safer than $0 for Bash scripts.'
  • The cd plus pwd step converts relative paths into an absolute directory.
  • Add extra logic only if you need to resolve symbolic links fully.
  • Use the script directory to build reliable paths to files shipped with the script.

Course illustration
Course illustration

All Rights Reserved.