What is `~sys`? It lists the content of `/dev`

In bash, when I type cd ~sys anywhere, I end up in /dev. In zsh it stays as ~sys in the prompt but contains /dev

I’ve checked on Kubuntu 22.04, Ubuntu 20.04, Raspbian 9.13.

Googling does not yield any results.

Asked By: Daniel F

||

The term ~sys refers to the home directory of the user sys. As can be seen by running getent passwd sys – its home directory is listed as /dev.

I’ve looked, but I’m not actually sure what is that user account – it is obviously a system account (as can be seen by its low id number of 3), and it belongs to a sys group (which is likewise a "system account group"), but on a modern Ubuntu installation it does not own or have access to any file or process. It may be a legacy thing.

Answered By: Guss

When you enter cd ~sys you are changing to the home directory of the user sys. Just like cd ~roaima would change to the home directory for user roaima. A shortcut to your own home directory is simply ~, so you may already know about using it for that.

In the password file (grep '^sys:' /etc/passwd or more generically getent passwd sys) you can see the home directory for sys is /dev:

sys:x:3:3:sys:/dev:/usr/sbin/nologin

which shows why cd ~sys changes you to the directory /dev.

Your original question mentioned just entering ~sys without a verb. In this instance the shell translated ~sys to its home directory, /dev and then tried to run it as a program. Obviously the directory can’t be a program so the attempt failed:

~sys
-bash: /dev: Is a directory

/dev
-bash: /dev: Is a directory

If you are running a shell such as bash you can override this behaviour and have the shell treat attempted execution of a directory as an indication to change into that directory (i.e. implied cd):

shopt -s autocd
~sys               # → "cd -- /dev"
pwd                # → "/dev"

~                  # → "cd -- /home/roaima"
pwd                # → "/home/roaima"

See Are there any caveats in using shopt -s autocd? for further discussion.

Answered By: roaima

~foo expands to the home directory of the user foo. This is a feature of almost every modern shell including bash, zsh, more generally all POSIX-compliant shells, BusyBox ash, (t)csh (where it originated) and fish.

Unix systems have a number of system accounts, some for good reason, others largely historical. These system accounts have a home directory, even though they never log in: that’s largely historical (and I’m not sure if leaving the field blank is properly supported, so they have to have something there anyhow, although it can be something like /nonexistent). Debian systems happen to have a system user called sys, which I think hasn’t been used for years (decades?) but is still present for backward compatibility. The home directory of that user is /dev. So ~sys expands to /dev in the shell and many other programs, just like ~daniel expands to /home/daniel (or whatever your username and home directory are).

In zsh, if (like most people) you include the %~ prompt escape sequence in your prompt, then your prompt includes the current directory (possibly abbreviated). If the current directory is under your home directory, that part is abbreviated to ~. Zsh takes this further and also abbreviates other directories that can be abbreviated through tilde expansion. In particular, if you’ve previously referred to some user’s home directory with the ~foo syntax, then zsh remembers that this directory can be abbreviated as ~foo.

Zsh calls this feature static named directories. The place where zsh remembers the named directories is the directory hash table, which you can access with the builtins hash -d and unhash -d.

darkstar% PS1='%~%% '
~% cd /dev
/dev% hash -d              # No known directory abbreviations so far
/dev% echo ~sys            # Let's use ~sys
~sys% hash -d              # Now ~sys=/dev, seen in the hash table and the prompt
sys=/dev
~sys% unhash -d sys        # Forget the abbreviation
/dev%                      # Now the prompt is no longer "abbreviated"

Annoyingly, zsh considers ~foo to be a worthwhile abbreviation of the home directory of foo if the “abbreviation” is shorter or as long as the original string. I make it forget named directories that are of equal length:

function chpwd_prompt {
    # If a user foo has the home directory /bar and length("foo") <
    # length("bar") then zsh shows `/bar' as `~foo'. If length("foo")
    # = length("bar") then zsh still favors `~foo', but I want `/bar'.
  if [[ ${(%):-%~} == ~* && ${#${(%):-%~}} -eq $#PWD ]]; then
    unhash -d -- ${${${(%):-%~}%%/*}#~}
  fi
}
chpwd_functions+=(chpwd_prompt)

This code can obviously be adapted to different preferences, for example to only ever abbreviate directories under /home, or only ~ itself (though for that it’s easier to start from %/ and replace your home directory only).

Indeed. For stuff that needs some extra access, but not full root, adm was generally for "administrative" uses and sys for "system" uses. Which is rather vague, but really that’s because these weren’t strictly standardized.

Apparently in Arch Linux in present day, adm gets access to files in /var/log that regular users can’t read, and sys has access to cups administration (which I must say is a little weird, lp is "line printer" and the traditional user/group for printing-related stuff.)

In Debian/Ubuntu sys is not used at all, probably uucp and several of those others aren’t either, but they are traditional and so left in. (With no password, shell set to nologin, and no files owned by them, they are effectively inert anyway so leaving them in doesn’t do any harm even from a theoretical security standpoint.)

Answered By: hwertz
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.