Why does cd ~k (& tab) expands to cd ~kernoops when I already have a folder named "~kernel-ppa" in pwd?

I have a folder named ~kernel-ppa inside ~/Downloads.

aditya@aditya-desktop:~$ cd Downloads/
aditya@aditya-desktop:~/Downloads$ ls
~kernel-ppa

Now when I type cd ~k and press Tab for automatic expansion, the shell expands it to cd ~kernoops/ instead of cd ~kernel-ppa/ although the folder with same starting characters is already present.

For automatic expansion to work, I need to escape it with \. Thus using cd \~k and pressing Tab correctly expands it to cd \~kernel-ppa/. Even using cd \ and pressing Tab does the trick.

Why is it so and why do I need to escape? Moreover, what am I escaping since even ~ is not required for automatic expansion?

If I go with the flow and run cd ~kernoops/ and press Enter, the terminal status changes to //:

aditya@aditya-desktop:~/Downloads$ cd ~kernoops/
aditya@aditya-desktop://$ pwd
//
aditya@aditya-desktop://$ ls
bin   cdrom  etc   initrd.img  lost+found  mnt  proc  run   srv  tmp  var
boot  dev    home  lib         media       opt  root  sbin  sys  usr  vmlinuz
aditya@aditya-desktop://$ 

This looks like the / directory, but pwd says it is //. What exactly is it?


As you know, ~ expands to your home directory. But what you seem to have missed is that ~john expands to the home directory of the user named "john".

Check your /etc/passwd file:

% grep ker /etc/passwd
kernoops:x:107:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false

It has a "system user" named kernoops (for internal bug reporting reasons). So when you type cd ~kTab the shell gives preference(1) to user name expansion before local directories expansion, and you have cd ~kernoops. Now it results that user "kernoops" home dir is /, so it cds to it.

In my shell, zsh, I have no double slash(2):

[:/] % cd ~kernoops/ 
[:/] % pwd
/
[:/] % cd //
[:/] % pwd
/

As an aside, this directory name is not well thought. It will need triple care in scripts and whatever. The only worst idea I can think is embedding a tab in it...


Footnotes:

(1) In zsh, even if I have a directory named ~xdir and no user starting with x; doing cd ~xTab does not expand and not quoting the ~ gives error:

[:~/tmp/x] %  mkdir \~xdir
[:~/tmp/x] % ls
~xdir
[:~/tmp/x] % cd ~xdir  
zsh: no such user or named directory: xdir
[:~/tmp/x] 1 % 

(2) I seem to remember that posix made an exception for the initial // in a path --- it should be maintained because some old unix variant (I used the apollos with Domain/OS that had that) used //machine-name/... to seamless access other machines' filesystem in the local network (security was not invented yet). So probably bash is right here. If you do cd /// you will have the normal / in both shell, though.

Yes, found on unix.se!


The tilde character (~) has a special meaning in the shell. When it is seen in any command, it is expanded to the name of your home directory. Doing cd ~ or cd /home/aditya is the same, it ends up in your home directory.

By putting a backslash character (\) in front of the tilde, you tell the shell to not do the expansion of the following special character (this is what is called shell escape). By doing cd \~ you ask the shell to move to a directory called ~ that would be located under the directory you are doing the command. So doing cd \~kernel-ppa will change you to the directory called ~kernel-ppa, which is the normal behaviour.

EDITED: more on ~

If you write a username of your system after the ~, you are moved to the home directory of that user. Doing a Tab expansion after cd ~ will expand to usernames existing on your system. If do Tab completion after cd ~k, it expands to ~kernoops because there is user named kernoops in the system user, with a home directory of /. As the expansion of cd ~k results into cd ~kernoops/ with a trailing slash and the home directory beeing /, you are moved to //. But this is strictly the same as / as someothers already said earlier.