Directory – Why Can’t List File/Directory Relative to .. from a Symlink Directory

cd-commanddirectorylssymlink

I have a /usr/tomcat6/logs directory linked to /var/log/tomcat6.

When I changed directory to /usr/tomcat6/logs and try to ls files using a relative pathname ../conf/Catalina/localhost, a No such file or directory error occurs. However, cd ../conf/Catalina/localhost works.

See the following:

[root@fedora ~]# ll /usr/tomcat*
lrwxrwxrwx. 1 root root 21 Jun 17 15:00 /usr/tomcat6 -> apache-tomcat-6.0.32/
lrwxrwxrwx. 1 root root 21 Jun 17 13:03 /usr/tomcat7 -> apache-tomcat-7.0.16/
[root@fedora ~]# cd /usr/tomcat6
[root@fedora tomcat6]# ll logs
lrwxrwxrwx. 1 root root 16 Jun 17 14:51 logs -> /var/log/tomcat6
[root@fedora tomcat6]# cd logs
[root@fedora logs]# cd ../conf/Catalina/localhost
[root@fedora localhost]# pwd
/usr/tomcat6/conf/Catalina/localhost
[root@fedora localhost]# cd /usr/tomcat6/logs
[root@fedora logs]# ll ../conf/Catalina/localhost
ls: cannot access ../conf/Catalina/localhost: No such file or directory

How could this happened? Is it a bug or special behaviour of symbolic link?

Best Answer

It is special behavior of bash's cd builtin; the relative file behavior is the natural one. Once you follow a symbolic link, you are in the actual path of the target and the original path information is lost; but if you use bash or zsh to cd there then the shell remembers the original path and uses it in future relative cd commands. But not in relative filename references, because bash doesn't actually know if you intended a filename or something else.

If you look at the cd documentation in bash, you'll see there are -L and -P options which tell it whether to use "logical" (remembering the original path) or "physical" (using the filesystem's idea) paths.

If you need to have the "logical" behavior at all times, you need to use a --bind mount (on Linux; Solaris and other OSes call it "loopback" or other things) instead of a symlink.