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:It has a "system user" named
kernoops
(for internal bug reporting reasons). So when you typecd ~k
Tab the shell gives preference(1) to user name expansion before local directories expansion, and you havecd ~kernoops
. Now it results that user "kernoops" home dir is/
, so itcd
s to it.In my shell,
zsh
, I have no double slash(2):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 withx
; doingcd ~x
Tab does not expand and not quoting the~
gives error:(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 docd ///
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. Doingcd ~
orcd /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 doingcd \~
you ask the shell to move to a directory called~
that would be located under the directory you are doing the command. So doingcd \~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 aftercd ~
will expand to usernames existing on your system. If do Tab completion aftercd ~k
, it expands to ~kernoops because there is user named kernoops in the system user, with a home directory of/
. As the expansion ofcd ~k
results intocd ~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.