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 link2
the 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.