Many systems have a getent
command to list or query the content of the Name Service databases like passwd
, group
, services
, protocols
...
getent passwd | cut -d: -f6
Would list the home directories (the 6th colon delimited field) of all the users in databases that can be enumerated.
The user name itself is in the first field, so for the list of user names:
getent passwd | cut -d: -f1
(note that it doesn't mean those users can login to the system or their home directory have been created, but that they are known to the system, they can be translated to a user id).
For databases that can't be enumerated, you can try and query each possible user id individually:
getent passwd {0..65535} | cut -d: -f1,6
(here assuming uids stop at 65535 (some systems support more) and a shell that supports zsh's {x..y}
form of brace expansion). But you wouldn't want to do that often on systems where the user database is networked (and there's limited local caching) like LDAP, NIS+, SQL... as that could imply a lot of network traffic (and load on the directory server) to make all those queries.
That also means that if there are several users sharing the same uid, you'll only get one entry for each uid, so miss the others.
If you don't have getent
, you could resort to perl
:
perl -le 'while (@e = getpwent) {print $e[7]}'
for getent passwd
($e[0]
for the user names), or:
perl -le 'for ($i=0;$i<65536;++$i) {
if (@e = getpwuid $i) {print $e[0] ": " $e[7]}}'
for getent passwd {0..65535}
with the same caveats.
In shells, you can use ~user
to get the home directory of user
, but in most shells, that only works for a limited set of user names (the list of allowed characters in user names supported for that ~
expansion operator varies from shell to shell) and with several shells (including bash
), ~$user
won't work (you'd need to resort to eval
when the name of the user is stored in a variable there). And you'd still have to find a way to get the list of user names.
Some shells have builtin support to get that list of usernames.
bash
: compgen -u
would return the list of users in databases that can be enumerated.
zsh
: the $userdirs
associative array maps user names to their home directory (also limited to databases that can be enumerated, but if you do a ~user
expansion for a user that is in a non-enumerable database, an entry will be added to $userdirs
). So you can do:
printf '%s => %s\n' "${(kv@)userdirs}"
to list users with their home directory.
That only works when zsh
is interactive though.
tcsh
, fish
and yash
are three other shells that can complete user names (for instance when completing ~<Tab>
arguments), but it doesn't look like they let you obtain that list of user names programmatically.
~
is generally the equivalent of/home/user
, not of/home
or/home/*
(which seem to be closer to your intention). – Soron Dec 07 '17 at 09:29nobody
) have their home directory set to/nonexistent
, which, obviously, does not exist. (Of course, those users also have their password hash set to*
and their shell set to/usr/sbin/nologin
or/bin/false
, so they really can't log in in the normal sense to begin with.) – Ilmari Karonen Dec 07 '17 at 14:25