7

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 
1
  • Also be aware, that links can be circular: a -> b b -> a Commented Mar 18, 2016 at 16:00

3 Answers 3

13

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

1
  • Thanks; but it doesn't give the information about intermediate file(s) (like /etc/alternatives/gnome-text-editor) which may be useful Commented Mar 18, 2016 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 
1
  • 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). Commented Mar 18, 2016 at 14:57

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.