6

Let me give an example (it's just an example taken from here):

$ ls -l /usr/bin/gnome-text-editor 
lrwxrwxrwx 1 root root 35 Mar 16  2015 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
$ ls -l /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 16  2015 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit
$ ls -l /usr/bin/gedit
-rwxr-xr-x 1 root root 588064 Mar 27  2014 /usr/bin/gedit

Here you can see that I've to use ls -l three times for reaching to destination. (3rd time is for making sure that /usr/bin/gedit is not a link`)

Is there any way (by means of making script or another command etc.) that I can get expected output like:

$ <improved ls -l> /usr/bin/gnome-text-editor 
lrwxrwxrwx 1 root root 35 Mar 16  2015 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 16  2015 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit

Another good output may be:

$ <some-command> /usr/bin/gnome-text-editor
/usr/bin/gnome-text-editor > /etc/alternatives/gnome-text-editor > /usr/bin/gedit
  • Also be aware, that links can be circular: a -> b b -> a – gilhad Mar 18 '16 at 16:00
12

In this case, that's a Debian "alternative", so to get more details, you could use:

$ update-alternatives --display gnome-text-editor
gnome-text-editor - auto mode
  link best version is /usr/bin/gedit
  link currently points to /usr/bin/gedit
  link gnome-text-editor is /usr/bin/gnome-text-editor
  slave gnome-text-editor.1.gz is /usr/share/man/man1/gnome-text-editor.1.gz
/usr/bin/gedit - priority 50
  slave gnome-text-editor.1.gz: /usr/share/man/man1/gedit.1.gz
/usr/bin/leafpad - priority 40
  slave gnome-text-editor.1.gz: /usr/share/man/man1/leafpad.1.gz

More generally, on Linux, you can use the namei command to know about all the symlinks involved in the resolution of a path (also mount points with -x):

$ namei -lx /usr/bin/gnome-text-editor
f: /usr/bin/gnome-text-editor
Drwxr-xr-x root root /
drwxr-xr-x root root usr
drwxr-xr-x root root bin
lrwxrwxrwx root root gnome-text-editor -> /etc/alternatives/gnome-text-editor
Drwxr-xr-x root root   /
drwxr-xr-x root root   etc
drwxr-xr-x root root   alternatives
lrwxrwxrwx root root   gnome-text-editor -> /usr/bin/gedit
Drwxr-xr-x root root     /
drwxr-xr-x root root     usr
drwxr-xr-x root root     bin
-rwxr-xr-x root root     gedit

For a more direct answer to your question, I'd do something like:

#! /bin/zsh -
zmodload zsh/stat || exit
ret=0
for file do
  n=0
  while
    ls -ld -- "$file" || ! ret=1 && [ -L "$file" ]
  do
    if ((++n > 40)) && [ ! -e "$file" ]; then
      echo >&2 too many symlinks
      ret=1
      break
    fi
    zstat -A target +link -- "$file" || ! ret=1 || break
    case $target in
      (/*) file=$target;;
      (*)  file=$file:h/$target
    esac
  done
done
exit "$ret"

That may not give you all the information you need to understand what's going on. Compare for instance:

$ ./resolve-symlink b/b/b/b/x/b
lrwxrwxrwx 1 stephane stephane 1 Mar 18 15:37 b/b/b/b/x/b -> a
lrwxrwxrwx 1 stephane stephane 4 Mar 18 15:37 b/b/b/b/x/a -> ../a
lrwxrwxrwx 1 stephane stephane 26 Mar 18 15:15 b/b/b/b/x/../a -> /usr/bin/gnome-text-editor
lrwxrwxrwx 1 root root 35 Nov  5  2013 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 15 12:21 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit
-rwxr-xr-x 1 root root 10344 Nov 12 17:18 /usr/bin/gedit

With:

$ namei -lx b/b/b/b/x/b
f: b/b/b/b/x/b
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane b -> .
drwxr-xr-x stephane stephane   .
lrwxrwxrwx stephane stephane x -> 2
drwxr-xr-x stephane stephane   2
lrwxrwxrwx stephane stephane b -> a
lrwxrwxrwx stephane stephane   a -> ../a
drwxr-xr-x stephane stephane     ..
lrwxrwxrwx stephane stephane     a -> /usr/bin/gnome-text-editor
Drwxr-xr-x root     root           /
drwxr-xr-x root     root           usr
drwxr-xr-x root     root           bin
lrwxrwxrwx root     root           gnome-text-editor -> /etc/alternatives/gnome-text-editor
Drwxr-xr-x root     root             /
drwxr-xr-x root     root             etc
drwxr-xr-x root     root             alternatives
lrwxrwxrwx root     root             gnome-text-editor -> /usr/bin/gedit
Drwxr-xr-x root     root               /
drwxr-xr-x root     root               usr
drwxr-xr-x root     root               bin
-rwxr-xr-x root     root               gedit
10

readlink is the command you are looking for.

$ readlink -e /usr/bin/gnome-text-editor
/usr/bin/gedit

Various flags (-f, -e, -m) are available according to how you'd like to behave in case of broken links - see man readlink for details.

  • Thanks; but it doesn't give the information about intermediate file(s) (like /etc/alternatives/gnome-text-editor) which may be useful – Pandya Mar 18 '16 at 16:05
2

You can use the following script:

$ cat myll
#!/bin/bash
name="$1"
while [[ -L "$name" ]]; do
ls -l "$name"; 
name=`readlink "$name"`;
done

Example output:

$ myll /usr/bin/gnome-text-editor
lrwxrwxrwx 1 root root 35 Mar 16  2015 /usr/bin/gnome-text-editor -> /etc/alternatives/gnome-text-editor
lrwxrwxrwx 1 root root 14 Mar 16  2015 /etc/alternatives/gnome-text-editor -> /usr/bin/gedit

Here [[ -L "$name" ]] checks whether file is link or not and readlink "$name" reads link and save it to variable name for next loop. And hence while [[ -L "$name" ]] loops until original target/file reached.


For second work-around, you can use:

#!/bin/bash
name="$1"
while [[ -L "$name" ]]; do
echo -n "$name > ";
name=`readlink "$name"`;
done
echo "$name"

Example output:

$ myls /usr/bin/gnome-text-editor
/usr/bin/gnome-text-editor > /etc/alternatives/gnome-text-editor > /usr/bin/gedit
  • 2
    That won't work properly for relative symlinks (as relative symlinks are relative to the symlink's host directory, not to your current working directory). – Stéphane Chazelas Mar 18 '16 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.