Bash: Getting the path of the current script

I've often wanted to make a script perform an action on some resource that's located relative to the script.E.g., run clang-format on all of the C++ files in a repository, without running clang-format on any generated files, or submodule content, and without the restriction that you need to run the script from the repository root.

SOURCE="${BASH_SOURCE[0]}"
SCRIPT_DIRECTORY="$(cd "$(dirname "$SOURCE")" >/dev/null && pwd)"

But if there are symlinks that you want to resolve, you need to resolve them until $SOURCE is no longer a symlink.This seems like a pretty niche thing that you might not want to do. I found in helpful in my ~/.bashrc because I clone my dotfiles repository to ~/.config/dotfiles/ and symlink the contents into my home directory.

SOURCE="${BASH_SOURCE[0]}"
# resolve $SOURCE until the file is no longer a symlink
while [ -h "$SOURCE" ]; do
    SCRIPT_DIRECTORY="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)"
    SOURCE="$(readlink "$SOURCE")"
    # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
    [[ $SOURCE != /* ]] && SOURCE="$SCRIPT_DIRECTORY/$SOURCE"
done
SCRIPT_DIRECTORY="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)"

Then take the path to the script directory, and resolve the relative path to whatever resource you're interested in.

RELATIVE_ASSET="$SCRIPT_DIRECTORY/../relative/path/to/asset/"
# Resolve $RELATIVE_ASSET to an absolute path. May or may not be necessary.
ABSOLUTE_ASSET="$(readlink --canonicalize --no-newline "$RELATIVE_ASSET")"

If your script is in a Git repository (and you expect it to be executed from a Git repository), you can also use

REPO_DIRECTORY=$(git rev-parse --show-toplevel)