What is the difference between home$ and ~$?

8,289

Solution 1

Whatever you're saying about ~$, home$, and /home$ doesn't make much sense.  I guess you're talking about your command line prompt; if so, it would have been useful to show what you typed and what happened (and then explained what you expected).

But I can read minds, so I believe that I understand the issue: ~ and ~user239887 (assuming user239887 is your real user name) mean the same thing.  If you were to type

cd ~gman

that would take you to my home directory, and your shell prompt would probably look something like /home/gman$.


In the beginning, the shell prompt was always two characters — a printing character and a space.  If you were a system administrator, your prompt was ""; otherwise, it was "" or "".  And then God said, "Let there be fancy shell prompts," and, lo, there were fancy shell prompts.  Shell prompts started showing the user's name, the system name, the time, and the phase of the moon (do you think I'm kidding?), all in color.

One of the most popular customizations to the shell prompt is to include the current directory.  Your shell prompt is probably your current directory followed by "".

Another cool thing™ was that you were able to specify your own home directory by typing "~".  Because of this, when your current directory is your home directory and your shell prompt is configured to display your current directory, then the shell prompt displays "~".  But anyplace else, it shows the actual pathname (except it might show "~gman" when you are in my home directory, /home/gman).

Your home directory is probably /home/user239887.  As I said earlier, you can refer to it as ~ or ~user239887.  When you login, you are in your home directory, so your prompt is "~$ ".  If you type cd .., then you go to the /home directory, which is the parent directory of your home directory, and your prompt becomes "/home$ ".

At the risk of repeating myself, NO, /home is not your home directory.  Your home directory is probably /home/user239887.  /home is the parent directory of your home directory.

Solution 2

The $HOME environment variable is commonly set and exported by login to the pathname of a user's home directory when a user logs in. A POSIX-compatible shell will use the value of this environment variable in a context when it should perform a ~ tilde expansion to complete a path to a username's home directory but the actual expanded field is otherwise null. Aside from its association with the shell's tilde expansion and with /bin/login the $HOME shell variable is in no other case exceptional - it is handled by the shell as any other shell variable might be. The shell's tilde expansion, however, is unique as shell expansions go in almost every way.

This is a little a difficult to grasp at first - and is probably why the tilde expansion is so underused despite its immunity to the many varied kinds of shell-expansion vulnerabilities that can often negatively affect the more common kinds.

The shell might portably consider a tilde eligible for expansion if read in any of the following contexts:

  1. Immediately follows either the first = or any colon-character in a shell-variable assignment.
  2. Begins any shell argument word.
  3. Begins a shell path and either completes at least one full properly delimited path component all alone or can verifiably do so with trailing context.

Even in these cases the ~ tilde will not be expanded if it is quoted, or if the context somehow precludes its expanding wholly to some user's home directory or the current value of the $HOME environment variable. In other words, the shell will not perform any tilde expansions if the context of the expansion is at all uncertain. While the shell will happily expand $var_not_var away to null, it will refuse every time to make similar guesses about a ~.

The $HOME substitution, for example, can only occur if the tilde's possible expansion field is null - which is to say that its position in the argument list unequivocally guarantees its eligibility for expansion because it is delimited on all sides.

The only other case that a tilde might be expanded is when its trailing context completely matches a verified system username - in which case it is substituted for a path to said user's assigned home directory as reported-on by the system. The shell should compare the context against a list of the system's registered users and only expand if the trailing context matches one of them.

To clarify what I mean by a null or not-null ~ expansion field, here are a few examples:

printf %s\\n ~some_user_name ~some_user_name/some_more_stuff

Both of the above expansion contexts are not null - the tilde can only expand to the pathname of some_user_name's home directory and only if there is such a registered username on the current system. The second ~ should expand (or not expand) identically to the first because the path / separator character delimits the trailing context. If the shell cannot verify the existence of some_user_name then the ~ should remain just a tilde.

printf %s\\n ~/some_user_name /~/ ~

But here the expansion fields for the first and third tildes are null. The first is delimited by the path separator char. The second is similarly delimited, but is not even considered for expansion because it does not lead the shell word. The first and third tildes should both expand to the current value of the $HOME environment variable, and the results of the expansion should be equivalent to:

printf %s\\n "$HOME"/some_user_name /~/ "$HOME"

Note that the "$HOME"/some_user_name path above need not actually exist to qualify the tilde for expansion - as is also true of the previous ~some_user_name/some_more_stuff example - which is a unique attribute among portable path expansions. Typical filename generation or shell globbing behavior as might be attempted with the special shell chars ?[* is only to expand these characters away if they match a resolved pathname but otherwise to let them remain literally. The tilde, however, instead adopts an arbitrary preassigned value - as specified in $HOME - when a match cannot be had so long as its expansion eligibility is absolute.

Note also that the quotes used above are intentional - while the ~ tilde expansion will not occur in quotes, the value of its expansion is always literal and never subject to further pathname expansions or shell splitting of any kind. It expands in the same way most other expansions require quotes to do - when it expands at all. This is (possibly very usefully) contrasted, of course, by the expansion behavior of the actual $HOME environment variable.

As I previously hinted, the ~ tilde expansion can only occur in either an argument or assignment context unless the expansion completes a delimited path component of an executable command. And so a ~ passed alone in command position will not be subject to expansion. It is therefore possible to assign a ~ shell alias such that the command:

~ ~

...results in two independently and uniquely expanded values which are processed entirely based on input context. A user might even define the ~ alias to define the value of the $HOME shell variable when called such that the second tilde's expansion is altered by the first (and possibly even vice-versa with recursion).

In fact, I like to think of the ~ tilde as a kind of argument alias. I often use it in combination with $IFS - to the effects of which its expansions are immune - and $* and eval. I consider that it lends itself remarkably well to $IFS contexts because - as a single character - it can either be removed from a string entirely with a single expansion, or else safely substitute in any number of other characters per occurrence as I desire it. An argument array that looks like:

"$argv1" ~ "$argv2" ~ "$argv3" ~

...might be (safely) any number of things at any given time by merely temporarily reassigning the value of $HOME to whatever I wish and reevaluating it. Such an argument array can even be generated from any other on the original argument delimiter points with a little dextrous application of $* substitutions.

Another construct I like to use is:

for HOME in ./* ~; do stuff w/ $HOME and ~; done

...which gets me two values for each iteration's assignment. To one of these I can freely apply parsing in the form of $IFS splitting or additional glob characters immediately alongisde the other which will always literally refer to the iteration's original argument value. And what's more, I can do these things side-by-side in the same command's argument list and without overly cluttering it with shell-quotes.

It is this last point, I think, which most clearly demonstrates the difference between $HOME and ~.

Solution 3

In shell, user's home directory is located in /home/username,

~ is shortcut for home directory of the current user using the shell,

~usr is shortcut for home directory of user with username usr, so ~usr is the same as /home/usr. If your username is usr, then ~ and ~usr are the same.

The home directory of current user is also saved in variable $HOME.

Share:
8,289

Related videos on Youtube

Yogesh Tripathi
Author by

Yogesh Tripathi

Updated on September 18, 2022

Comments

  • Yogesh Tripathi
    Yogesh Tripathi over 1 year

    In the below screenshot, I was not able to understand the third shortcut of Table 2-1.

    It says that cd ~user_name will change the working directory to the home directory of the user_name. But, when I entered this command, I was in the same directory i.e, ~$ and not in /home$. Why?

    Are they both same ?

    I think the formal one is the user directory and the later one is the home directory.

    Screenshot

  • Walter A
    Walter A about 9 years
    ~ and ~user239887 mean the same thing when you are logged in as user239887.
  • Yogesh Tripathi
    Yogesh Tripathi about 9 years
    if /home/user_name is called home directory of user_name than what /home is called ?
  • Walter A
    Walter A about 9 years
    @user239887 The string ` /home$` is not part of a normal command. $HOME is a variable set to your homedir. Your homedir is defined in /etc/passwd and might be /home/user239887.
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' about 9 years
    @user239887: Please explain what you are talking about when you say /home$.
  • Yogesh Tripathi
    Yogesh Tripathi about 9 years
    on entering command cd ../ the prompt change from ~$ to /home$ that is why i have asked if /home is home directory than why /home/user_name is called home directory
  • user43791
    user43791 about 9 years
    @user239887 I think you misunderstood one thing : /home is NOT the home directory. It is the directory that contains all home directories. Your home directory is ~, which is the same as saying /home/your_username, but in no case is /home the home directory of anybody.
  • Yogesh Tripathi
    Yogesh Tripathi about 9 years
    ok thanks! /home doesn't mean home directory .it is parent directory of home directory right?
  • user43791
    user43791 about 9 years
    @user239887 right.