Why does mkdir fail (no such file or directory) in a script with BIN_DIR="~/bin/"?

Solution 1:

It doesn't work because ~ is quoted. Double quotes " suppress tilde expansion. There is no directory with the literal name ~/bin. As explained in man bash (emphasis mine):

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.

You can remove the quotes, since ~ is the only character in the path ~/bin that will cause the shell to perform an expansion, and we want the expansion in this case. The shell won't perform any further expansions on the result of tilde expansion, at least in Bash 4, which all current or remotely recent releases of Ubuntu have. So even if your home directory contains unusual characters like spaces, it's okay.

Or you can use $HOME instead of ~, because parameter expansion is not suppressed by double quotes, only by single quotes. The double quotes do ensure that the expanded value is not itself subject to any further expansions, so word splitting or filename expansion will not occur. So $HOME works even with strangely named home directories, too, so long as you keep the double quotes.

Solution 2:

The error message is produced because the tilde ~ is quoted, as described in Zanna's answer. If you want to use the ~, the relevant part of the script should be:

BIN_DIR=~/bin/

If for whatever reason you want to quote the string, you can use the environment variable $HOME:

BIN_DIR="$HOME/bin/"

In my opinion the second approach is better practice.