Skip to main content

This does what realpath from coreutils does, but works without it. Requires readlink instead. Recursively resolve all symlinks at the specified path and then print the final, absolute path.

#
# Print the absolute path of the target path. Note that the path must be a
# real path to a file or directory or else this will fail.
#
# $1: the target file or directory
#
# https://github.com/dansimau/bashlib/blob/master/bash.sh#L112
absolute_path() {
    local path=$1

    if [ "$path" == "." ]; then
        echo "$(pwd)"
    elif [ "$path" == ".." ]; then
        echo "$(dirname "$(pwd)")"
    else
        path="$(
            cd "$(dirname "$1")"
            pwd
        )/$(basename "$1")"
        # Replace double slashes, happens when we're operating at the root
        echo "${path/\/\///}"
    fi
}

#
# Recursively resolve symlinks
#
# This does what `realpath` from coreutils does but works without it. Requires
# readlink instead.
#
# Recursively resolve all symlinks at the specified path and then print the
# final, absolute path.
#
# https://github.com/dansimau/bashlib/blob/master/bash.sh#L139
resolve_symlinks() {
    (
        local path=$1

        while [ -L "$path" ]; do
            dir="$(dirname "$(absolute_path "$path")")"
            cd "$dir"
            path=$(readlink "$path")
        done

        echo "$(absolute_path "$path")"
    )
}