How can I search for symlinks that point to other symlinks? [closed]
Solution 1:
Following the entire link chain
realpath
realpath(1) gets you the absolute destination of a link. But it only gives you the final destination, so if you have a link chain, it will only show you the path of the last real file/folder that the chain eventually points to.
So in your case, if ../../e/f/g/h
is real file or folder, you will see the absolute path. But if one of the components is also a symlink, it will keep recursively until it resolves all the symlinks in the way.
readlink
You could also use the readlink(1)
command with the -f or -e flags, which will give you similar result to realpath
.
-f, --canonicalize canonicalize by following every symlink in
every component of the given name recursively;
all but the last component must exist
-e, --canonicalize-existing canonicalize by following every symlink in
every component of the given name recursively,
all components must exist
Avoid following the entire link chain
If I understand correctly, you don't want to follow the chain to the last component, but to only get the absolute path of the actual link. It's a little ugly, but you can do something such as:
LINK=./a/b/c/d
/usr/bin/realpath --no-symlinks "$(dirname ${LINK})/$(readlink ${LINK})"
Explanation:
$ dirname $LINK # dirname ./a/b/c/d
./a/b/c
$ readlink $LINK # readlink ./a/b/c/d
../../e/f/g/h
$ echo "$(dirname ${LINK})/$(readlink ${LINK})"
./a/b/c/../../e/f/g/h
$ /usr/bin/realpath --no-symlinks "$(dirname ${LINK})/$(readlink ${LINK})"
/home/a/e/f/g/h
If you only want to see the link relative to your CWD, you can add the --relative-to argument:
$ /usr/bin/realpath --no-symlinks --relative-to ./ "$(dirname ${LINK})/$(readlink ${LINK})"
a/e/f/g/h
Using find
You can get the argument for the realpath command I've shown before by using the find command:
$ find ./ -type l -printf "%h/%l\n"
./a/b/c/../../e/f/g/h
From man find:
%h Leading directories of file's name (all but the last element). If
the file name contains no slashes (since it is in the current
directory) the %h specifier expands to ".".
%l Object of symbolic link (empty string if file is not a symbolic link).
Then you could combine it with the realpath command from above.
$ find ./ -type l -printf "%h/%l\n" | xargs /usr/bin/realpath -s
/home/a/e/f/g/h
If you only want to see the link relative to your CWD:
$ find ./ -type l -printf "%h/%l\n" | xargs /usr/bin/realpath -s --relative-to ./
a/e/f/g/h