I'’ve tried Googling but not getting anywhere. How can I list all the members of a group called mygroup
from the command line in OS X?
dscl . list /groups
Will get me all the groups. But how can I see each group’s members?
Super User is a question and answer site for computer enthusiasts and power users. It only takes a minute to sign up.
Sign up to join this communityYou can use:
dscacheutil -q group -a name admin
or:
dscacheutil -q group -a name staff
etc.
dscacheutil -q group -a name admin
only gave me 1 result, whereas the Accepted Answer's shell script gave me 2 results.
There's no standard command that lists all members of a group in OS X, so here's a shell function which does that:
members () { dscl . -list /Users | while read user; do printf "$user "; dsmemberutil checkmembership -U "$user" -G "$*"; done | grep "is a member" | cut -d " " -f 1; };
Copy the above command-line to the Terminal, and then type members mygroup
(where mygroup is the name of an existing group).
Some explanation for those who are interested:
There are five different ways (that I know of) that a user can be member of a group in OS X. The command dscl . -read /Groups/mygroup GroupMembership
isn't guaranteed to output all, or even any, of mygroup's members, because membership also comes from users' primary group ID, membership by user's UUID, inheritance of membership from one group to another, and memberships that are calculated by the system, such as the group everyone.
So rather than trying to keep track of all those, it seems like a better idea to simply check the membership of every user on the system (using dsmemberutil), and that's what the shell function and the script below do.
This members script is equivalent to the shell function, but has nicer handling of invalid input:
#!/bin/bash
# members -- list all members of a group
#
# SYNOPSIS
# members groupname
#
# http://superuser.com/questions/279891/list-all-members-of-a-group-mac-os-x
# by Arne
# Expected to work on Mac OS 10.5 and newer, tested on 10.6 and 10.7.
# It could be rewritten to work on 10.4 by using "dseditgroup -o checkmember"
# instead of "dsmemberutil checkmembership".
# By using dseditgroup, the script could also be extended to handle
# other Directory Service nodes than the default local node.
#
the_group="$1"
# Input check and usage
if [[ $# != 1 || $1 == -* || $1 =~ [[:space:]] ]]; then
echo "Usage: ${0##*/} groupname" >&2
echo "Lists all members of the group." >&2
exit 64
elif (dsmemberutil checkmembership -U root -G "$the_group" 2>&1 \
| grep "group .* cannot be found") >&2; then
exit 1
fi
# Check every user
exec dscl . -list /Users \
| while read each_username
do
printf "$each_username "
dsmemberutil checkmembership -U "$each_username" -G "$the_group"
done \
| grep "is a member" | cut -d " " -f 1
# eof
Supplementary info:
The five ways of being a group member are:
These can be explored with commands like dscl . -read /Groups/somegroup
Example of 4: Membership of the Print Operator group __lpoperator_ is inherited by members of the Print Administrator group __lpadmin_, and membership of that group is inherited by the members of the admin group.
Example of 5:
$ dscl . -read /Groups/netaccounts Comment
Comment:
Group membership calculated by system
Accounts from a remote directory server
$
SEE ALSO
id(1), dscl(1), dsmemberutil(1), dseditgroup(8), DirectoryServiceAttributes(7), uuid(3)
Note: This was my initial answer, written before I realized this answer still gives an incomplete result. (For example, it finds no members of the everyone group!) So I wrote a better answer, which includes a script that lists all members of a group in OS X.
mygroup's GroupMembership property can be printed with dscl like this:
dscl . -read /Groups/mygroup GroupMembership
But this isn't guaranteed to output all (or even any) of the group's members. What's missing are the users who are member of the group only by having it as their primary group ID.
A common example of this in OS X are regular login accounts, which have staff (group 20) as their primary group, but are not listed in the GroupMembership property of the staff group.
Those users can be found by searching for the numeric primary group ID (gid) like this example for the staff group (gid 20):
dscl . -list /Users PrimaryGroupID | grep " 20$"
and the numeric gid (PrimaryGroupID) of mygroup is found by:
dscl . -read /Groups/mygroup PrimaryGroupID
To get all the groups that a user is in, you could use the following:
id -nG <username>
Example Output:
staff com.apple.sharepoint.group.1 everyone localaccounts _appserverusr admin _appserveradm _lpadmin _appstore _lpoperator _developer com.apple.access_ftp com.apple.access_screensharing com.apple.access_ssh
Utilising the command above, it is possible to get all users that belong to a group:
OSX:
group=staff;
for i in $(dscl . list /users);
do [[ $(id -nG $i | grep $group) ]] && echo $i;
done
Unix:
group=sudo;
# This only outputs lines that match a username (from the start of line to a colon must not be a hash indicating a comment)
for i in $(grep -oE "^[^#:]+" /etc/passwd);
do [[ $(id -nG $i | grep $group) ]] && echo $i;
done
dscl . -read /Groups/[groupname] | grep GroupMembership
BE AWARE: The command above does not always display a complete list of ALL group members. E.g. for the group "staff" you only get "root" as a group member which is incomplete. To check it use one of the following commands as a default user (NOT "root"): id -Gn
OR groups
As a result you will see all groups your default logged user is a member of. One of them should be "staff". Thus, besides "root" there are more members of the group "staff", which are not listed by the command dscl . -read /Groups/[groupname] | grep GroupMembership
. The same goes for the command dscacheutil -q group -a name staff
which also suggests you that only "root" is a member of the group "staff", which is obviously incomplete.
The only reliable method to get really ALL members of a group in the terminal on OSX is already provided here by Arne Stenström. This is using his shell function resp. his shell script. Both works great!
Command
Similar to @duperuser's answer, the following will print out only the users of the group admin
with spaces in between:
dscacheutil -q group -a name admin | grep -e '^users:' | sed 's/users: //'
Output
Running the above command will produce something like this:
root your_username someone_else
Breakdown
The dscacheutil
command is used to query information about various categories of the system's Directory Service cache. The -q
option lets you specify the category you want to query. The available categories are group, host, mount, protocol, rpc, service, and user. We further query that category by specifying a key value pair with the -a
option. In this case, we want to list the group having the key name
equal to the value admin
. The dscacheutil
command above produces output like this:
name: admin
password: *
gid: 80
users: root yourusername
Next we pipe this text into grep
and pick out the line containing the string users:
at the beginning. The -e
option makes grep recognize regular expressions. The ^
character specifies that we want users:
to be at the beginning of the line.
This gives us
users: root yourusername
Finally, we pass this into sed and replace the text users:
with the empty string. In sed, the first letter s
means to substitute. The text between the first pair of slashes (/users: /
) is what we want to replace, and the next pair of slashes (//
) is what we want to substitute (in this case, nothing).
Here is an implementation for this problem which was derived from an implementation in a related discussion. The routine is somewhat generic, with a directory service lookup hook for any specific platform/architecture, so it can be used without modification on a heterogenous network. We've installed a symbolic link to this utility named zed
. Other origins for this implementation are mentioned in the attribution section of the script. This tool is intended to be run on at least OSX, HP-UX, linux, and SunOS, but hasn't been tested on SunOS and HP-UX. The script was tested as far as possible on Ubuntu Linux 12.04 and Mavericks OSX 10.9.1. The output of this script matches the output for the first shell script implementation for this problem, and is therefore considered correct.
#!/usr/bin/perl
#
# Lists members of all groups, or optionally just the group
# specified on the command line
#
# Date: 12/30/2013
# Author: William H. McCloskey, Jr.
# Changes: Added logic to detect host type & tailor subset of getent (OSX)
# Attribution:
# The logic for this script was directly lifted from Zed Pobre's work.
# See below for Copyright notice.
# The idea to use dscl to emulate a subset of the now defunct getent on OSX
# came from
# http://zzamboni.org/\
# brt/2008/01/21/how-to-emulate-unix-getent-with-macosxs-dscl/
# with an example implementation lifted from
# https://github.com/petere/getent-osx/blob/master/getent
#
# Copyright © 2010-2013 by Zed Pobre ([email protected] or [email protected])
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
use strict; use warnings;
$ENV{"PATH"} = "/usr/bin:/bin";
# Only run on supported $os:
my $os;
($os)=(`uname -a` =~ /^([\w-]+)/);
unless ($os =~ /(HU-UX|SunOS|Linux|Darwin)/)
{die "\$getent or equiv. does not exist: Cannot run on $os\n";}
my $wantedgroup = shift;
my %groupmembers;
my @users;
# Acquire the list of @users based on what is available on this OS:
if ($os =~ /(SunOS|Linux|HP-UX)/) {
#HP-UX & Solaris assumed to be like Linux; they have not been tested.
my $usertext = `getent passwd`;
@users = $usertext =~ /^([a-zA-Z0-9_-]+):/gm;
};
if ($os =~ /Darwin/) {
@users = `dscl . -ls /Users`;
chop @users;
}
# Now just do what Zed did - thanks Zed.
foreach my $userid (@users)
{
my $usergrouptext = `id -Gn $userid`;
my @grouplist = split(' ',$usergrouptext);
foreach my $group (@grouplist)
{
$groupmembers{$group}->{$userid} = 1;
}
}
if($wantedgroup)
{
print_group_members($wantedgroup);
}
else
{
foreach my $group (sort keys %groupmembers)
{
print "Group ",$group," has the following members:\n";
print_group_members($group);
print "\n";
}
}
sub print_group_members
{
my ($group) = @_;
return unless $group;
foreach my $member (sort keys %{$groupmembers{$group}})
{
print $member,"\n";
}
}