Update: I have found an interesting forum discussion on the double slash behavior. Older *nix systems used a // path and a /../ path prefix to mean a network filesystem. A hostname would be added, like //victim/etc/shadow. POSIX leaves the double slash to be handled in an implementation-specific fashion. After hearing this, the people on the forum start complaining about how bash is the only shell that does this and that bash is free to do it any way it wants and therefore sucks. This just isn’t true, because bash doesn’t own the filesystem. Bash doesn’t understand the filesystem. Bash just makes system calls and the Linux VFS actually figures out what these slashes mean. Linux’s specific implementation is to ignore it. If bash were to remove the extra leading slash, it would be doing the kernel’s job of interpreting paths. This is why cool things like FUSE and NFS work: Every single little program doesn’t try to understand what the filesystem is. It just takes the path, asks the kernel, and the kernel replies with a file descriptor that looks like a directory or file or pipe or socket or whatever it wants. The kernel has the power to do anything when asked for the contents of a path. It handles finding and distributing the files, and userland just uses it and pretends to like it.
How many times have you done this?
It happens to me more often than I can count. It’s incredibly annoying and even dangerous if you’re mucking about in sensitive places on your system. In most cases when this happens, you meant to type “cd ..” to go up one folder. Instead, you’re placed in some half-assed root directory.
I was pretty annoyed by this after a couple of times and wanted to fix it. First I tried something like “touch //” or “touch /\/” so that typing “cd //” would fail because it’s a file. No dice, it thinks I’m trying to touch the root directory. So I tried an alias; I set up cd to alias to a script which detects the “//” and changes it to “..” and then executed the chdir(). This didn’t work because the script is launched in a subshell and so it’s cwd is independent from my shell’s. I tried again: alias cd=”cd $(mycd)” where mycd echo’s the appropriate path. This won’t work because afaik there’s no way to pass the argument from the outer shell to the inner.
Needless to say, this greatly frustrated me. In desperation and anger I grabbed The Source and started poking around. After looking at things and a few dumb segfaults, I figured out a (hacky) workaround that’s “good enough for me.”
It’s a patch to builtins/cd.def in the bash 4.1 tarball. It’s only six lines including whitespace, is a dirty hack and probably won’t be making it into the main tree anytime soon, but it solved a major headache for myself, so hopefully someone can benefit from it:
I’m not sure why “//” is considered a valid path. All other variations on /+ take you to the root, with just one slash. “//” moves you to something called “//”, however. Very odd how that one name is somehow different from the others. There could be a valid semantic reason for this behavior I’m unaware of that something depends on, so I wouldn’t use this as my system-wide shell before looking into it, just a login shell.