20

cd ~

does the same thing as

cd $HOME

which is also the same as

cd /home/tandu

However,

cd ~not-tandu

changes to /home/not-tandu

Is this purely a syntactic choice? How is this handled by the kernel (or the cd execuable?) Is there a special case for ~ to add the slash if everything else is omitted? That is to say, ~/ and ~ change to the same directory, but ~a is one directory up. The same cannot be said for any other directory you change to.

3
  • 3
    Feel free to compare ~not-tandu and ~/not-tandu, one points to the user not-tandu home dir and the other points to the dir not-tandu in your homedir.
    – Johan
    Mar 17, 2012 at 7:50
  • 5
    It's not the kernel or the "cd executable" (since there is no such thing) - it's a shell built-in. Mar 17, 2012 at 11:47
  • Since you not mention it: cd without any parameters works like cd ~. If you replace cd with echo you can see to what the expression is expanded by the shell.
    – jofel
    Mar 17, 2012 at 23:43

3 Answers 3

25

~ is an alias for $HOME provided by a number of shells, but $HOME is more universal. $HOME actually asks the shell to insert (substitute) the environmental variable HOME here. There are quite a number of different environmental variable that can be substituted, try running env for a list. Note that ~ is not always recognized when it's not at the beginning of a word. Try these two commands for comparison:

ls /~
ls /$HOME

The first gets passed to the ls executable as /~ which then tries to look at a file called ~ in the root directory, the second expands $HOME and becomes //home/user which is then passed to the ls executable as a command-line argument. All POSIX systems (POSIX is the standard for how UNIX and Linux systems operate) allow multiple slashes to be treated the same as one slash so //home/user is the same as saying /home/user. ~username is a shortcut for telling the shell to look up username in the passwd file and return their home directory. There is no equivalent environment variable. All of these substitution are done by the shell and are supported by most of them, but only environment variables like $HOME are guaranteed to be supported by all shells. Also, cd is actually a built-in command. It's a special directive that tells the shell itself to change directories. It's not like other shell built-ins that can be implemented as a separate executable like echo is because it's used to change a fundamental attribute of the shell process. echo is merely a shell built-in for performance reasons, but in the good old days of UNIX, was only available as it's own executable /bin/echo.

1
  • re "which then tries to look at a file called ~ in the root directory"; That's for all unix flavors?
    – Pacerier
    May 25, 2019 at 13:41
17

~foo means 'the home directory of user foo'.

This isn't done by the kernel, it's interpreted by the shell. Whenever the shell sees ~foo as an argument, it transparently replaces it with the home directory of user foo and passes that in its place. So when you run cd ~tandu, the shell is actually running cd /home/tandu.

4
  • 1
    What specifically does this replacement and with what algorithm? Is it cd or the shell? What if you are not running a shell? Is it a simple "if ~ is followed by something, expand differently?" or is there some other special handling for this unique condition? Mar 17, 2012 at 5:29
  • 9
    See the Bash manual on Tilde Expansion. (Many other shells and programs follow similar rules.)
    – cjm
    Mar 17, 2012 at 6:17
  • 4
    @tandu: the shell does cd, there is not external executable to do it (it wouldn't be possible)
    – Mat
    Mar 17, 2012 at 6:40
  • 1
    @tandu: if you're not running a shell (e.g. trying this out using exec(2)), shell expansion doesn't take place. Without shell expansion, ~ doesn't get replaced by anything — it's just another perfectly valid character. This bit me in my early SunOS days because /bin/sh didn't grok ~.
    – Alexios
    Mar 17, 2012 at 13:16
6

~ followed by a username expands to that user's home directory.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .