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
source: https://muffinresearch.co.uk/bash-resolving-symlinks-to-shellscripts/
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:

```bash
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:

```bash
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;
        fi

        cd "$(dirname "$script_symlink_path")"

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

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

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

    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:

```bash
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.