cd ~ is possible but why can't we cd ~“$USER” or cd ~${USER}

2018-05-19 02:51:16

I am curious why can't we switch to a user's home director with either

$ cd ~"$USER"

or

$ cd ~${USER}

That very much depend on the shell and the order the expansions are done in those shells.

~$user expands to the home directory of the user whose name is stored in $user in csh (where that ~user feature comes from), AT&T ksh, zsh, fish.

Note however these variations:

$ u=daemon/xxx csh -c 'echo ~$u'

/usr/sbin/xxx # same in zsh/fish

$ u=daemon/xxx ksh93 -c 'echo ~$u'

~daemon/xxx

$ u=daemon/xxx csh -c 'echo ~"$u"'

Unknown user: daemon/xxx.

$ u=daemon/xxx zsh -c 'echo ~"$u"'

/usr/sbin/x # same in fish

$ u=" daemon" csh -c 'echo ~$u'

/home/stephane daemon

$ u=" daemon" zsh -c 'echo ~$u'

~ daemon # same in ksh/fish

$ u="/daemon" csh -c 'echo ~$u'

/home/stephane/daemon # same in zsh

$ u="/daemon" fish -c 'echo ~$u'

~/daemon # same in ksh

It expands to the home directory of the user named literally $user in bash (provided that user exists which is very u

  • That very much depend on the shell and the order the expansions are done in those shells.

    ~$user expands to the home directory of the user whose name is stored in $user in csh (where that ~user feature comes from), AT&T ksh, zsh, fish.

    Note however these variations:

    $ u=daemon/xxx csh -c 'echo ~$u'

    /usr/sbin/xxx # same in zsh/fish

    $ u=daemon/xxx ksh93 -c 'echo ~$u'

    ~daemon/xxx

    $ u=daemon/xxx csh -c 'echo ~"$u"'

    Unknown user: daemon/xxx.

    $ u=daemon/xxx zsh -c 'echo ~"$u"'

    /usr/sbin/x # same in fish

    $ u=" daemon" csh -c 'echo ~$u'

    /home/stephane daemon

    $ u=" daemon" zsh -c 'echo ~$u'

    ~ daemon # same in ksh/fish

    $ u="/daemon" csh -c 'echo ~$u'

    /home/stephane/daemon # same in zsh

    $ u="/daemon" fish -c 'echo ~$u'

    ~/daemon # same in ksh

    It expands to the home directory of the user named literally $user in bash (provided that user exists which is very unlikely of course).

    And to neither in pdksh, dash, yash, presumably because they don't consider $user is a valid user name.

    2018-05-19 02:57:35
  • Tilde expansion is a separate step in the processing of the command line. It happens just before variable expansion.

    If the tilde is followed by something other than a slash, it will expand to the home directory of the user whose name is following the tilde, as in, for example, ~otheruser. Since $USER is not expanded at that point and since it's unlikely to correspond to a valid username, the tilde is left unexpanded.

    $USER is likely to be the username of the current user, so your expression could probably be replaced by just ~.

    2018-05-19 03:23:12
  • As other answers have pointed out the behavior depends on which order the shell does ~ and $ expansions and whether it will even do both for the same word.

    The behavior you were looking for is possible to achieve in bash by a very small change to your command. Simply prefix the command with eval.

    eval "cd ~$USER"

    will change to the home directory of the user given by the username in the variable USER, provided $USER doesn't contain characters special to the shell (if there's a remote chance that it might, you should not pass it as argument to eval as that would be dangerous) or / characters and that there's an entry for that user in the system's user database.

    2018-05-19 03:27:34
  • An alternative way to look up a variable user's home directory, if you are using one of the shells where tilde expansion happens before variable expansion, is with getent. This tool exists on at least Linux, Solaris, and FreeBSD; I'm not sure how universal it is.

    $ USER=bloggs

    $ getent passwd "$USER" | cut -d: -f6

    /home/b/bloggs

    As with tilde expansion, this might not give you the same thing that su - $USER -c 'echo $HOME' would print if you had the privileges to do that.

    2018-05-19 03:54:31
  • Since the OP insists on an answer, here it is.

    The behavior of those commands (and many other things) depends on the particular shell you happen to be using. Unless you specifiy which particular shell you use, it is probably not possible to give a simple answer.

    As a matter of fact, if you use tcsh, as I do, both of the expressions in the OP's question (as it is written as I write this - I take no responsibility for future edits!) work perfectly well. I don't know what other shells will do, since I don't use them. So perhaps the OP doesn't know quite as much about what can be done as s/he thinks :-)

    2018-05-19 04:02:04