Say that I setup a symbolic link:
ln -s /root/Public/mytextfile.txt /root/Public/myothertextfile.txt
is there a way to see what the target of myothertextfile.txt
is using the command line?
Say that I setup a symbolic link:
ln -s /root/Public/mytextfile.txt /root/Public/myothertextfile.txt
is there a way to see what the target of myothertextfile.txt
is using the command line?
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
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
This will also work:
ls -l /root/Public/myothertextfile.txt
but readlink
would be preferred for use in a script rather than parsing ls
.
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”.
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}"
}
If you can't use readlink
, then parsing the result of ls -l
could be done like this.
The normal result would be:
ls -l /root/Public/myothertextfile.txt
lrwxrwxrwx 1 root root 30 Jan 1 12:00 /root/Public/myothertextfile.txt -> /root/Public/mytextfile.txt
So we want to replace everything before " -> " and the arrow included. We could use sed
for this:
ls -l /root/Public/myothertextfile.txt | sed 's/^.* -> //'
/root/Public/mytextfile.txt
The question is not accurate enough to give a simple answer as the one of brian-brazil:
readlink -f some_path
will indeed dereference every symlink involved in the path construct to the final target behind some_path
.
But one level of cascading symlinks is just a particular case among others in a system, the general case being N levels of cascading symlinks. Look at the following on my system:
$ rwhich emacs
/usr/bin/emacs
/etc/alternatives/emacs
/usr/bin/emacs24-x
rwhich
is my own recursive implementation of which
that prints all of the intermediate cascading symlinks (to stderr) down to the final target (to stdout).
Then if I want to know what is:
the target of symlink /usr/bin/emacs**, the obvious answer to me is /etc/alternatives/emacs
as returned by:
readlink $(which emacs)
readlink /usr/bin/emacs
the final target behind cascading symlinks /usr/bin/emacs, the answer shall be /usr/bin/emacs24-x
as returned by:
readlink -f $(which emacs)
readlink -f /usr/bin/emacs
rwhich emacs 2>/dev/null
ll
or ls -l
should list the directory items, including your symbolic link and it's target
cd -P /root/Public/myothertextfile.txt
(in your case) should point to the original path
If you find the target of all links within a folder and its subfolder use the find . -type l -ls
command with link type as follows:
me@local.localdomain:~/test$ find . -type l -ls
8601855888 0 lrwxr-xr-x 1 me staff 6 Jan 24 19:53 ./link -> target
If you want the target of a single, then ls -l
should work:
me@local.localdomain:~/test$ ls -l
total 0
lrwxr-xr-x 1 me staff 6 Jan 24 19:53 link -> target
-rw-r--r-- 1 me staff 0 Jan 24 19:53 target