readlink -f and -e option description not clear

First component here means an element of the path. Example :

/home/user/.ssh => <component1>/<component2>/<component3>

1- Suppose we have a directories structure like this :

lols
├── lol
├── lol1 -> lol
└── lol2 -> lol1

And also the non-existent directory here will be lols/lol3 So you can compare the output of each command :

readlink -f lols/lol1 : /lols/lol
readlink -e lols/lol1 : /lols/lol

The output here will be the same because all the components of the path exists.

readlink -f lols/lol8 : lols/lol8
readlink -e lols/lol8 : <empty outpyt>

The output here is different because with -f it will show the result because there is one component that exists at least in the path which is lols and with -e the output will be empty because all path components must exist.

And the last one is with having multiple non-existent directories :

readlink -f lols/lol8/lol10 : <empty output>
readlink -e lols/lol8/lol10 : <empty output>

Here the output will be empty because as described in the map page : -f : all but the last component must exist => Not respected -o : all components must exist => Not respected

2- Why not use only ls -l :

Suppose we create a file named file1 and create asymlink to this file named link1 and from link1 create another symlink link2 :

touch file1 : file1 
ln -s file1 link1 : link1 -> file1
ln -s link1 link2 : link2 -> link1

Then with ls -l link2 the output will be : link2 -> link1 And if we use readlink link2 the output will be : link1 ; same as ls -l But if we use readlink -f|-e link2the output will be : file1 ; so it will point to the source file.

So when to use readlink instead of ls ? When there is a nested symlinks (Recursive Read). When the files/directories are on a different locations.

So better to use readlink instead of ls to avoid errors.


This is meaningful for links following a route over more than one hops until their final target. For example:

touch test_file

ln -s test_file test_link
ln -s non_existing_target dead_link

ln -s test_link link1
ln -s dead_link link2

In the above, link1 is finally linking to a file, through test_link, so -f and -e would give the same result. link2 is pointing to a dead link, and you see that:

> readlink -e link2
> readlink -f link2
/home/thanasis/temp/non_existing_target

dead_link is the "last component" in the expression "all but the last component must exist". -f is resolving to the target that doesn't exist, while -e is giving no output.


Note that man readlink recommends that

realpath is the preferred command to use for canonicalization functionality

For this example, realpath -m, (--missing) would give the same output to readlink -f. In general realpath -e is the way to test if a link can be resolved to a final existing target file, which is returning the expected error here:

> realpath -e link2
realpath: link2: No such file or directory

While ls -l returns all results and probably has some red color output for any dead links. Also the option -L exists, to dereference the links and show their target, this is for humans to read, never use ls to decide anything about a link inside a script.