Reputation: 51
I started studying bash from the very beginning. I decided to practice using shortcuts for the current directory and the parent directory (dot and double dot). I noticed some strange behavior of the latter with the bin folder. To show this strangeness, I will first show how it works with home directory, and then how it works with bin.
Like the home directory, directories etc, mnt, boot work correctly. But bin does not. Can someone explain why this is?
Upvotes: 2
Views: 79
Reputation: 13491
/bin
is probably a symbolic link to /usr/bin
. At least it is a link to somewhere. But since I know some unix system have /bin
be a symlink to /usr/bin
, plus the fact that the content of your displayed /bin/..
is the same as /usr
on my machine (on which there is no such symlink tho, but on my previous arch, there was).
So, have a look at ls -ld /bin
You'll see that it is a link to /usr/bin
or to ../usr/bin
.
So /bin/..
is really /usr/bin/..
that is /usr
(An experiment to show that this would be exactly what happen if /bin
was a symlink to /usr/bin
)
Set up some mock tree (I use capital for directories, and touch a file that shows full (full from my mock root Tmp) path each dir)
mkdir Tmp
touch Tmp/root
mkdir Tmp/Usr
touch Tmp/Usr/usr
mkdir Tmp/Usr/Bin
touch Tmp/Usr/Bin/usr.bin
cd Tmp
ln -s Usr/Bin Bin
cd ..
From there we can see that
ls -ld Tmp/Bin
is a link (obviously, since I made it that way. Just since you discover all that, want to make clear that this is what your saw on your actual system) : Tmp/Bin -> Usr/Bin
And therefore that
ls Tmp/Bin/..
shows
Bin usr
That is the content of Tmp/Usr
, not the one of Tmp
(that would be root
)
But, indeed
cd Tmp/bin/..
ls
shows
Bin root Usr
That is the content of Tmp
not Tmp/Usr
, as if Tmp/Bin
parent were Tmp
As for why, it is important to understand that cd
is not a program (unlike ls
, cp
, etc.). It is a shell command. So it can have a different (in this case, documented), behaviour. Well, theoretically, any program can have its own interpretation of those ..
; what they are passed is just a string, such as bin/..
, what they do with it, is up to them. But most would do just a open
or opendir
, with that string argument, and that would lead bin/..
to be interpreted as you have seen ls
do.
cd
acts differently, as the documentation says (man bash
)
If .. appears in dir, it is processed by removing the immediately previous pathname component from dir
In other words, cd foo/bar/bla/..
means cd foo/bar
whatever those are in reality. Especially, if bla is a symlink to a different place far for foo/bar
, it doesn't matter. cd
process first, transparently, without even caring what the filesystem have to say about those (or even if they make any sense from the filesystum point of view. It is just some string processing), is to remove any ..
and what immediately precedes it, from the chain of /
separated substring. And then, and only then, it starts to bother with reality of filesystem.
You can force it, tho, to act as another command would do, that is to resolve what is really foo/bar/bla/..
or Tmp/Bin/..
or /bin/..
, by using option -P
The -P option causes cd to use the physical directory structure by resolving symbolic links while traversing dir and before processing instances of .. in dir
cd -P Tmp/Bin/..
ls
shows indeed
Bin usr
as you were expecting (that is what ls Tmp/Bin/..
would show
Lastly, the reason of that choice from cd
, frankly I have no idea. What I know is that unix system call chdir
(man 2 chdir
) does behave like the bash command with -P
flag. So reason is not a Unix reason. More a bash choice.
For example, tcsh
(another shell. The one that was quite standard when I learned Unix, and still exists today) acts differently
$ tcsh
> cd Tmp/Bin/..
> ls
shows
Bin usr
(Note that I use ls
and my touched files to know where cd
goes. Obviously pwd
is the tool to know where I am. I do so only because your initial question was about ls
)
So, different shells, different behavior. This is not a Unix thing, but a bash thing (and sh, and zsh, ...)
Upvotes: 5