Edit: This is a duplicate of https://stackoverflow.com/questions/998626/meaning-of-tilde-in-linux-bash-not-home-directory/. I don’t have the reputation to close this question as duplicate.
I’m not referring to ~ as in the home directory but rather this:
$ ls ~foo/bar /some/mount/point/foo/bar
However if I attempt it with a different mount point, e.g.:
$ mount | ag "/dev " devfs on /dev (devfs, local, nobrowse) $ ls /dev/stdin /dev/stdin $ ls ~stdin zsh: no such user or named directory: stdin . # bash has a similar error message: ls: ~stdin: No such file or directory
What is the ~ called in this context? How does it work?
Edit:
More information based on some of the comments below:
- I can attest that
foois not a username on my system. - When attempting to autocomplete
ls -lah ~not all options are shown. i.e. I’m able tocd ~qux, whenquxdoesn’t show up in the autocomplete. Againquxis not a user in my system. - If it matters
/some/mount/pointis a network share. - All of the details suggest some named path muckery, a Z shell feature of pathname expansion, but this works in bash as well, which apparently doesn’t support things like the Z shell’s named paths.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
What is ~foo
Quote from bash manual (with added emphasis):
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.
~foo expands to foo user’s home directory exactly as specified in /etc/passwd. Note, that this can include system usernames; it doesn’t necessarily mean human users or that they can actually log in locally ( they can log in via SSH keys for instance).
In fact, as noted in the comments, bash will use getpwnam function. That function itself is specified by POSIX standard, hence should exist on most Unix-like systems, including macOS X. This function isn’t limited to /etc/passwd only and searches other databases, such as LDAP and NIS. Particular excerpt from bash source code, tilde.c file, starting at line 394:
/* No preexpansion hook, or the preexpansion hook failed. Look in the
password database. */
dirname = (char *)NULL;
#if defined (HAVE_GETPWNAM)
user_entry = getpwnam (username);
#else
user_entry = 0;
Practical example
Below you can see tests with system usernames on my system. Pay attention to corresponding passwd entry and result of ls ~username
$ grep '_apt' /etc/passwd _apt:x:104:65534::/nonexistent:/bin/false $ ls ~_apt ls: cannot access '/nonexistent': No such file or directory $ grep '^lp' /etc/passwd lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin $ ls ~lp ls: cannot access '/var/spool/lpd': No such file or directory
Even if for instance _apt account is locked as suggested by output of passwd -S apt it is still showing up as possible login name:
_apt L 11/29/2017 0 99999 7 -1
Please note: This is not macOS specific feature, but rather shell-specific feature.
Method 2
In summary of why you are seeing something for ~foo/bar, it is because you have a user named foo on the system with a folder named bar in their home directory.
See this solution in another community that explains why (tilde) ~ is more than just “home directory”.
If you have a user named bin on your system, then you can list the contents of bin’s home directory by the command:
ls ~bin
One other thing you can try is to use tab completion after typing the following at a prompt (don’t carriage return, just use the tab key):
ls -lah ~ tab
to see the list of users’ home directories that ~ will expand to if you continue to. Example (truncated) output of tab completion of ls -lah ~ tab
$ ls -lah ~ ~antman/ ~games/ ~bin/ ~mail/
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0