143
votes

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?

9 Answers 9

187
votes

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 
5
  • 8
    As suggested in another question, you may want to use readlink -f. Commented Jun 7, 2014 at 0:14
  • 5
    To get this working on Mac OS X, brew install coreutils. This installs basic gnu versions of commands prefixed with the letter g, i.e. greadlink -f somefile Commented Feb 21, 2016 at 20:47
  • with -f switch, command returns nothing in my case.. Commented Jul 19, 2018 at 8:08
  • Using -f gave me the information that I wanted, i.e. resolving multiple symlinks and showing the end target. Commented Oct 15, 2018 at 19:52
  • on Ubuntu 18.04.1 LTS (Bionic Beaver) the manpages of readlink have a note saying "Note realpath(1) is the preferred command to use for canonicalization functionality." Commented Jul 1, 2019 at 15:32
24
votes

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 
1
  • 1
    Nothing wrong with the first answer, but this one is more complete and helpful. Commented May 11, 2018 at 15:30
6
votes

This will also work:

ls -l /root/Public/myothertextfile.txt 

but readlink would be preferred for use in a script rather than parsing ls.

5
votes

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”.

0
3
votes

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}" } 
1
vote

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 
1
vote

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 
0
votes

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

0
votes

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:

[email protected]:~/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:

[email protected]:~/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 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.