Difference between $HOME and ~

$HOME and ~ usually refer to the same thing. That is, they are the path to the "user's home" directory which is of the general form "/home/userName".

When, if ever, do these not refer to the same directory?


Solution 1:

Both $HOME and ~ point to the same folder, the current user's home folder, but both are very different things.

  • $HOME is an environment variable, that is set to contain the home folder of the current user.
  • ~ is a shell expansion symbol, i.e., one of the symbols that is processed before the actual command is performed. ~ alone expands to the value of $HOME. ~nemo expands to the home directory of user nemo. A shell expansion symbol is a character (or pair of characters) that is processed/interpreted by the shell to build the actual command. Another example of a shell expansion symbol is *, which is used to expand file names.

Solution 2:

One way they differ is in how the Bash shell converts them when enclosed in the " kind of quotation marks.

If you use echo like this, without any quotes, then ~ and $HOME have the same effect:

$ echo ~
/home/elias
$ echo $HOME
/home/elias

However, with " quotation marks around them, the result differs:

$ echo "~"
~
$ echo "$HOME"
/home/elias

Solution 3:

~ only expands as a part of a tilde-prefix which by definition must start at the beginning of the word. Additionally, as it was once part of globbing patterns, ~ will not work inside double quotes. So, "~" or a~b will result in a literal value of ~ being preserved.

A single ~ (or a ~ followed by a /) will expand to current user's home:

$ echo ~/.ssh
/home/user/.ssh

A ~ followed by a username will expand to home folder of that user:

$ echo ~root/.ssh
/root/.ssh

A ~ followed by a + or a - and an optional number will expand to elements of the directory stack:

$ cd /etc
$ echo ~+0
/etc

$HOME is the equivalent of a single ~, which instead follows syntax rules for variables. For instance, it expands inside double quotes, can be unset, and string manipulation operands can be applied to it.

Solution 4:

This depends a lot on what does the expansion. In bash, ~ is a convenient way to get the home directory without triggering filename expansion or word splitting even though its unquoted. For example:

$ HOME='/*'
$ echo $HOME
/bin /boot /dev /etc /home /lib /lib64 /media /mnt /opt /proc /root /run /sbin /srv /sys /tmp /usr /var
$ echo ~
/*

Or:

$ HOME='/ a b'
$ printf "|%s|\n" $HOME ~
|/|
|a|
|b|
|/ a b|

So if you're wrestling with quotes for some reason (in which case you should really re-think the whole thing, it's easier to wrestle pigs), ~ might be more convenient.


Elsewhere, in Python, for example, ~ and $HOME have to be expanded by different functions. Some other places allow variables and don't allow other shell syntax like wildcards or tilde expansion (e.g., ~/.pam_environment, which has a special syntax for variable expansion). Yet other places allow tilde expansion as an exception (e.g., systemd), but query the passwd database directly instead of using $HOME.

Solution 5:

$HOME/ is more likely to work in standard POSIX.2 Bourne /bin/sh as tilde expansion is an extension found in BSD csh tcsh GNU bash and others.

If you want to write scripts portable to busybox or dash or BSD sh, invest in the extra letters lest you crash with ~/: No such file or directory on certain systems.

I also find $HOME/ more readable.