Ubuntu – How does using the tilde work as a shortcut to the home directory


I was confused, trying to copy some files from one PC to another. I have it figured out, but the syntax is still confusing to me.
This works:

scp ~/Desktop/Volenteer.png jay@server.ip:~j0h/b

which puts Volenteer.png in the folder /home/j0h/b. However, this doesn't work:

scp ~Desktop/Volenteer.png     jay@server.ip:~j0h/b

This also fails, giving an exit status 1 file not found:

scp ~/Desktop/Volenteer.png     jay@server.ip:~/j0h/b

As does this:

scp ~Desktop/Volenteer.png     jay@server.ip:~j0h/b

So clearly, there is some difference between ~ and ~/
That difference is the presence of /

bash: /home/j0h/: Is a directory
$ ~
bash: /home/j0h: Is a directory

So why in scp, does the ~ resolve to ~/ ?
That is a guess, I cant verify that's what is happening.
But it seems inconsistent, and therefore confusing.
Is this a bug in scp? or is there something about tilde I am missing?

Best Answer

~ is your home directory.

~foo is the home directory of user foo, if such a user exists, or just a directory named ~foo, if that user doesn't exist.

Hence, in:

scp ~Desktop/Volenteer.png     jay@server.ip:~j0h/b

~Desktop will expand to home directory of user Desktop, if such a user exists (and it usually does not), or be just ~Desktop (a path which usually does not exist either).


scp ~/Desktop/Volenteer.png     jay@server.ip:~/j0h/b

~/j0h will expand to a directory named j0h in jay's home directory, which, again, is unlikely to exist.

It's not ~ and ~/ where the difference occurs, but in ~ and ~foo.

Additionally, ~ can also be used for directory history navigation:

  • ~- is the previous working directory (like $OLDPWD)
  • ~+ is the current working directory (like $PWD)

This is not applicable to scp, since you don't get to change directories in the middle of an scp operation.

And if you use pushd and popd to maintain a directory stack, ~N and ~+N would be the N th directory in the directory stack, as seen in the output of dirs. ~-N would be the N th directory from the end (counting from zero, in both cases). For example:

$ for i in etc usr var tmp; do pushd /$i; done
/etc ~/.vim
/usr /etc ~/.vim
/var /usr /etc ~/.vim
/tmp /var /usr /etc ~/.vim

$ dirs
/tmp /var /usr /etc ~/.vim

Then, the directories in the stack can be accessed using:

/tmp /var /usr /etc ~/.vim
  ~0   ~1   ~2   ~3     ~4
 ~+0  ~+1  ~+2  ~+3    ~+4
 ~-4  ~-3  ~-2  ~-1    ~-0 
  ~+   ~-