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 ~k
Tab 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 cd
s 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 ~x
Tab 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.