Are my Linux symbolic links acting correctly?

I've been using Linux on and off for the last 15 years and today I came across something in bash that surprised me.

Setup the following directory structure:

$ cd /tmp
$ mkdir /tmp/symlinktest
$ mkdir /tmp/symlinktest/dir
$ mkdir /tmp/symlinktarget

Now create two sym links in symlinktest pointing to symlinktarget:

$ cd /tmp/symlinktest
$ ln -s ../symlinktarget Asym
$ ln -s ../symlinktarget Bsym

Now, in bash, the following tab completion does strange things. Type the following:

$ cd dir
$ cd ../A[TAB]

Pressing the tab key above completes the line to:

$ cd ../Asym/

as I expected. Now press enter to change into Asym and type:

$ cd ../B[TAB]

This time pressing the tab key completes the link to:

$ cd ../Bsym[space]

Note that there is now a space after the Bsym and there is no trailing slash.

My question is, why when changing from the physical directory "dir" to Asym it recognises that Asym is a link to a directory, but when changing from one sym link to another, it doesn't recognise that it's a link to a directory?

In addition, if I try to create a new file within Asym, I get an error message:

$ cd /tmp/symlinktest/Asym
$ cat hello > ../Bsym/file.txt
-bash: ../Bsym/file.txt: No such file or directory

I always thought that symlinks were mostly transparent except to programs that need to manipulate them. Is this normal behaviour?

Many thanks,

Andy


bash's cd builtin does a bit of magic with ...

When you do:

cd ../Bsym

It looks at $PWD, removes the last component, adds the Bsym component. This is what cd and cd -L do, as opposed to cd -P. Also see pwd -L and pwd -P.

When you do:

cat hello > ../Bsym/file.txt

This magic doesn't take place. $PWD isn't used, /proc/self/cwd is used instead. The cwd is an inode, and .. is just the parent inode, which happens to be /tmp.