Skip to main content

Resolve symlinks that call a bash shell script.

title: Resolving symlinks to shell scripts in Bash
subtitle: "Here's a way to resolve symlinks that call a bash shell script"
author: Stuart Colville
date: October 10, 2008
notoc: false

> Here's a way to resolve symlinks that call a bash shell script.

## The Problem

I like to be able to use something like this in my bash scripts:

SCRIPTDIR=$(dirname "$0")

Which is great for a reference to where the script is, but it suffers from the
problem that if you symlink to that script `$0` now refers to the symlink rather
than the actual script.

## The Solution

The ~~hack~~ solution is to use the following instead:

resolve_symlink() {
    local script_symlink_path=$1
    local script_abs_path=''

    until [ "$script_symlink_path" = "$script_abs_path" ]; do
        if [ "${script_symlink_path:0:1}" = '.' ];
            then script_symlink_path=$PWD/$script_symlink_path;

        cd "$(dirname "$script_symlink_path")"

        if [ ! "${script_symlink_path:0:1}" = '.' ]; then
            script_symlink_path=$(basename "$script_symlink_path");

        script_abs_path=$(ls -l "$script_symlink_path" | awk '{ print $NF }')

    if [ ! "${script_symlink_path:0:1}" = '/' ]; then

    echo "$(dirname "$script_symlink_path")"

# Usage:
DIR=$(resolve_symlink $0)
echo "$DIR"

This updated version should fix the shortcomings of the previous version pointed
out in the first comment by resolving links that are relative as well as link
chains. Whilst readlink works for linux systems the script above should be
portable across unixes which was the original intention.

If you can rely on python then there's an even easier way:

DIR=$(python -c "import os; print os.path.realpath(\"${0}\")")
echo "$DIR"

But again portability is the key.

Find any issues or have improvements to add please let me know.