In zsh, there's a modifier for that, or rather two: A
to resolve symbolic links (with realpath) and h
to extract the “head” (i.e. the dirname
).
cd $file(:A:h)
This only works if the symbolic isn't broken. If there is a chain of symbolic links, it is followed until the ultimate target. If the directory was reached through a symbolic link, you'll be in its target (as with cd -P
).
Without zsh, if you have the readlink
utility, and you want to change to the directory containing the target of the symbolic link:
cd -- "$(dirname -- "$(readlink -- "$file")")"
The target of the link could be itself a symlink. If you want to change to the directory containing the ultimate target of the link, you can call readlink
in a loop:
while [ -L "$file" ]; do
target=$(readlink -- "$file")
while case $target in */) target=${target%/};; *) false;; esac; done
case $target in
*/*) cd -- "${target%/*}"; target=${target#**/};;
esac
done
On Linux, assuming the symlink isn't broken, you can use readlink -f
to canonicalize the path:
t=$(readlink -f -- "$file")
cd "${t%/*}"