Given a canonical pathname, such as yours, this will work:
set -f --; IFS=/
for p in $pathname
do [ -e "$*/$p" ] || break
set -- "$@" "$p"
done; printf %s\\n "$*"
That prints through the last fully existing/accessible component of $pathname, and puts each of those separately into the arg array. The first nonexistent component is not printed, but it is saved in $p.
You might approach it oppositely:
until cd -- "$path" && cd -
do case $path in
(*[!/]/*)
path="${path%/*}"
;; (*) ! break
esac
done 2>/dev/null && cd -
That will either return appropriately or will pare down $path as needed. It declines to attempt a change to /, but if successful will print both your current working directory and the directory to which it changes to stdout. Your current $PWD will be put in $OLDPWD as well.
access(2)is not very granular, so the solution typically involves writing something to iterate and test each path element in turn... – thrig Feb 03 '16 at 23:53