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
Answer
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
.
No comments:
Post a Comment