Find out symbolic link target via command line
Solution 1:
Use the -f
flag to print the canonicalized version. For example:
readlink -f /root/Public/myothertextfile.txt
From man readlink
:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Solution 2:
readlink is the command you want. You should look at the man page for the command. Because if you want to follow a chain of symbolic links to the actual file, then you need the -e or -f switch:
$ ln -s foooooo zipzip # fooooo doesn't actually exist
$ ln -s zipzip zapzap
$ # Follows it, but doesn't let you know the file doesn't actually exist
$ readlink -f zapzap
/home/kbrandt/scrap/foooooo
$ # Follows it, but file not there
$ readlink -e zapzap
$ # Follows it, but just to the next symlink
$ readlink zapzap
zipzip
Solution 3:
This will also work:
ls -l /root/Public/myothertextfile.txt
but readlink
would be preferred for use in a script rather than parsing ls
.
Solution 4:
If you want to show the source and the destination of the link, try stat -c%N files*
. E.g.
$ stat -c%N /dev/fd/*
‘/dev/fd/0’ -> ‘/dev/pts/4’
‘/dev/fd/1’ -> ‘/dev/pts/4’
It’s not good for parsing (use readlink
for that), but it shows link name and destination, without the clutter of ls -l
-c
can be written --format
and %N
means “quoted file name with dereference if symbolic link”.
Solution 5:
The readlink
is a good thing, but GNU-specific and non cross platform. I used to write cross platform scripts for /bin/sh
, therefore I'd use something like:
ls -l /root/Public/myothertextfile.txt | awk '{print $NF}'
or:
ls -l /root/Public/myothertextfile.txt | awk -F"-> " '{print $2}'
but these needs to be tested on different platforms. I think they'll work, but don't 100% sure for ls
output format.
The result of ls
can also be parsed within bash
without depending on an external command like awk
, sed
or perl
.
This bash_realpath
function, resolves the final destination of a link (link→link→link→final):
bash_realpath() {
# print the resolved path
# @params
# 1: the path to resolve
# @return
# >&1: the resolved link path
local path="${1}"
while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
do
path="${BASH_REMATCH[1]}"
done
echo "${path}"
}