MacOS – Any difference between ~ and $HOME

command linemacos

It would appear that ~ and $HOME are equivalent in command line and shell scripts. Is that true?

Best Answer

It's true to a certain extent.

  • $HOME is an expression for expansion of the environment variable HOME
  • ~ (tilde) is a separate shell expansion component see footnote

When used as a command argument and in separation from other strings, $HOME and ~ are usually equivalent.

But there are cases where they differ:

  • if the string containing either is quoted, for example:

    # echo "My home directory is $HOME"
    My home directory is /Users/techraf
    # echo "My home directory is ~"
    My home directory is ~
    
  • if they are concatenated to a string, for example:

    • dd if=${HOME}/source_file of=${HOME}/destination_file will work.

      Shell will pass arguments if=/Users/techraf/source_file and of=/Users/techraf/destination_file containing a valid path to the dd command.

    • dd if=~/source_file of=~/destination_file won't work

      Shell will pass arguments if=~/source_file and of=~/destination_file to the dd command and it will report an error as it does not interpret ~.


footnote:

In fact ~ is by default replaced with the value of HOME, but if HOME is empty, it is resolved to a home directory:

# echo $HOME
/Users/techraf
# export HOME=/dummy
# echo $HOME
/dummy
# echo ~
/dummy

# unset HOME
# echo $HOME

# echo ~
/Users/techraf

From man bash:

Tilde Expansion

If a word begins with an unquoted tilde character (`~'), all of the characters preceding the first unquoted slash (or all characters, if there is no unquoted slash) are considered a tilde-prefix. If none of the characters in the tilde-prefix are quoted, the characters in the tilde-prefix following the tilde are treated as a possible login name. If this login name is the null string, the tilde is replaced with the value of the shell parameter HOME.

If HOME is unset, the home directory of the user executing the shell is substituted instead. Otherwise, the tilde-prefix is replaced with the home directory associated with the specified login name.