Today my friend Mat told me an interesting trivia fact about cd!
Look at this interaction, where we try to
cd //tmp, and
cd ///tmp, in bash and in fish.
bork@kiwi/> bash bork@kiwi:/$ cd //tmp bork@kiwi://tmp$ echo $PWD //tmp bork@kiwi:/tmp$ cd ///tmp bork@kiwi:/tmp$ echo $PWD /tmp bork@kiwi://tmp$ fish Welcome to fish, the friendly interactive shell Type help for instructions on how to use fish bork@kiwi:/tmp> cd //tmp bork@kiwi:/tmp> echo $PWD /tmp
//tmp? What is happening? Why is
cd ///tmp different from
cd //tmp? Here’s what we know so far:
// the same file?
Yes. We can check this with
stat. They both have the same inode number (256)
so they are the same file.
bork@kiwi:~$ stat / File: '/' Size: 244 Blocks: 0 IO Block: 4096 directory Device: 16h/22d Inode: 256 Links: 1 Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2017-02-08 23:13:55.647187990 -0500 Modify: 2017-01-10 13:01:30.987733887 -0500 Change: 2017-01-10 13:01:30.987733887 -0500 Birth: - bork@kiwi:~$ stat // File: '//' Size: 244 Blocks: 0 IO Block: 4096 directory Device: 16h/22d Inode: 256 Links: 1 Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2017-02-08 23:13:55.647187990 -0500 Modify: 2017-01-10 13:01:30.987733887 -0500 Change: 2017-01-10 13:01:30.987733887 -0500 Birth: -
Cool. But what is
//? Why doesn’t bash just correct it to
The specification for cd is here
Here’s the relevant section
An implementation may further simplify curpath by removing any trailing <slash> characters that are not also leading <slash> characters, replacing multiple non-leading consecutive <slash> characters with a single <slash>, and replacing three or more leading <slash> characters with a single <slash>. If, as a result of this canonicalization, the curpath variable is null, no further steps shall be taken.
So! We can replace “three or more leading / characters with a single
slash”. That does not say anything about what to do when there are 2
characters though, which presumably is why
cd //tmp leaves you at
Why is this the specification? Mat pointed out there is a “Rationale” section in this spec, but it does not really explained.
In another specification, it says:
A pathname that begins with two successive slashes may be interpreted in an implementation-defined manner
So you can define
//tmp to mean whatever you want? Like it could be different
/tmp? Why? Somebody on stack overflow said that this is related to the
double slash in URLs (“http://“…) but didn’t provide a citation. Is that
If I find out, I will update this blog post with an answer.
update 1: there seems to be a pretty good answer in this stack overflow question