cd to directory of a symbolically linked file
Solution 1
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%/*}"
Solution 2
You can use readlink
to resolve the symbolic link and then dirname
to get its directory.
cdl () {
cd "$(dirname "$(readlink "$1")")";
}
bash-3.2$ pwd
/foo/bar
bash-3.2$ ls -l
total 8
lrwxr-xr-x 1 root wheel 11 Jun 15 19:10 foo.sh -> /bar/foo.sh
bash-3.2$ cdl foo.sh
bash-3.2$ pwd
/bar
bash-3.2$
Related videos on Youtube
Chauncey Garrett
Updated on September 18, 2022Comments
-
Chauncey Garrett almost 2 years
Before I write a script, anyone know an easy way to do the following:
$ pwd /foo/bar $ ls -l lrwxr-xr-x 1 username admin 48 Apr 17 2012 foo.sh -> /bar/foo.sh $ cd /bar $ ls foo.sh
i.e., in the directory
/foo/bar
, I'd like to do something likecdl
(cd link), which would take me to the directory of the linked file (or alternatively to the linked directory, if that happened to be the case—if it was I could typecd -P /bar
).-
200_success about 11 yearsMay I ask what your motivation is for doing this? Also, do you want to resolve symlinks recursively? (If /bar is itself a symlink, would you want to follow it?)
-
-
Kevin about 11 yearsN.B. this is a perfect example of why to use
$()
instead of backticks. -
Chauncey Garrett about 11 yearsExcellent answer:
cd $file(:A:h)
is exactly what I was looking for! -
Jakob Bennemann almost 10 yearsThis is your second one-line answer (it even appears to be exactly the same answer). Again, one-line answers are not the most helpful. Please expand your answers to include more helpful information and explanation (including supporting links and documentation).