#!/bin/sh case "$1" in /*) left="${1#/}" ;; *) left="${PWD#/}/$1" ;; esac result="" while [ -n "$left" ]; do case "$left" in */*) # Snip one path segment off $left seg="${left%%/*}" left="${left#*/}" ;; *) # Last path segment already seg="$left" left="" ;; esac case "$seg" in .) # Just ignore this segment continue ;; ..) # Eat a segment off result result="${result%/*}" continue ;; esac result="$result/$seg" target="$(readlink "$result")" case "$target" in /*) # Absolute symlink. Resets buildup of $result left="${target}/${left}" result="" ;; '') # Readlink failed, its not a symlink # If file does not exist, exit [ -e "$result" ] || exit 1 ;; *) # Relative symlink: Keep $result, its the symlink base left="${target}/${left}" result="${result%/*}" ;; esac # Make sure $left never starts with a slash left="${left#/}" done printf "%s\n" "$result"