3

How to get a list of usernames assigned to a group in FreeBSD 11.1?

This Question asks for a list of users or a list of groups.

This Question asks for users who happen to be members of multiple specific groups.

➥ But how to ask simply for a list of users currently assigned to a single specific group, such wheel?

I prefer a solution in a single command if possible. But if not feasible, a script would be useful and educational.

5 Answers5

6

You can select users with specific group from list of all users given by pw utility:

pw usershow -P -a | grep groupname

Result will be something like:

Login Name: username1     #1024         Group: groupname          #1002
Login Name: username2     #1025         Group: groupname          #1002
2

The proper way to show all users in a certain group under FreeBSD is:

# pw groupshow groupname
2

Disregarding system scripts commands like getent, users can be in a group in two ways: either it is their principal group, defined in /etc/passwd, or they have it as a secondary group in /etc/groups.

GROUPID=1000
sed -rn "s/^[^:]*:[^:]*:$GROUPID://p" < /etc/group | tr ',' '\n'
sed -rn "s/^([^:]*):[^:]*:[^:]*:$GROUPID:.*/\\1/p" < /etc/passwd

Should do it nicely. awk would probably look nicer...

GROUPID=1000
awk -F: -v "g=$GROUPID" '{if ($3==g) print $1;}' /etc/passwd
awk -F: -v "g=$GROUPID" '{if ($3==g) print $4;}' /etc/group | tr ',' '\n'
Law29
  • 3,617
  • 1
  • 18
  • 30
1

This answer assumes you use exclusively portable group and user identifiers as defined by the POSIX™ standard.

  • If you exclusively care about explicit group membership, i. e. statements “group X contains members …” as defined via an /etc/group file, you can use:

    • Excluding network user accounts:
      pw group show operator # or groupshow
      
    • Including users from other database sources as defined by /etc/nsswitch.conf:
      getent group family
      

    Either output can be filtered into a more readable form:

    … | cut -d':' -f4 | tr ',' ' ' | fmt
    
  • If you want to learn about group membership including the primary group as defined via the 4th field of the traditional passwd text file database format, you need to either

    • ensure all such group membership definitions are logged explicitly (and redundantly) in /etc/group, too,
    • or deduce this information from available data.

    The former is not recommended or supported. The latter can be achieved in multiple ways.

    • Write a shell script such as:
      #!/bin/sh -u
      #        name: members
      # description: show members of a group, or nothing in case of unknown groups
      #  maintainer: J Doe <mailbox@host> # fill in in multi-sysadmin environments
      getent group "${1:-}" | {
          # Determine the numeric group identifier and get explicit group members.
          # NB: Shell variables may experience a size limit.
          IFS=':' read -r group_name group_password group_identifier group_members
      
      # Now find implicit group members using the numeric group identifier.
      getent passwd | grep &quot;^..*:..*:..*:${group_identifier}:&quot; | cut -d':' -f1
      
      # Since the preceding pipeline prints each user name on its own line,
      # print `${group_members}` one line each, too.
      [ &quot;${group_members}&quot; ] &amp;&amp; printf '%s\n' &quot;${group_members}&quot; | tr ',' '\n'
      

      } | sort -u # | { tr '\n' ' ' ; printf '\n' ; } # if you prefer

      EOF

      Or a bit slower since you need to repeatedly spawn a process (id):
      #!/bin/sh -u
      #        name: members
      # description: show members of a group, the group name matching a shell pattern
      #  maintainer: B Bourque <mailbox@host> # fill in in multi-sysadmin environments
      
      # In shell patterns asterisks expand to strings of any length (including 0).
      # The surrounding spaces are necessary for anchoring.
      expression="* ${1:?Error: Specify one group name as argument.} *"
      
      getent passwd | while IFS=':' read -r username remainder
      do
          # `id -G` obtains all groups a user belongs to,
          # including the primary group specified in `passwd`.
          # The `-n` flag resolves numeric IDs to textual representations.
          groups=" $(id -Gn ${username}) "
          # The `##` means “remove largest prefix pattern”.
          # If the string becomes an empty string by this operation,
          # `[ "" ]` returns `false` so the `||` (“or else”) applies.
          [ "${groups##${expression}}" ] || printf '%s\n' "${username}"
      done | sort
      # EOF
      

      The latter implementation may be useful if you have group names following a certain pattern, e. g. departmentX, departmentY, departmentZ. If you want to find users belonging to any department, you can invoke the script as

      ./members.sh 'department*' # '…' to inhibit expansion in the invoking shell
      
    • If you have the shells/bash, shells/zsh or other feature‑rich shell port installed, you can perform text file operations using process substitution. Process substitution is the language construct of choice, because the join utility can handle at most one pipe (- for standard input) as parameter. Replace operator as appropriate.
      join -t':' -1'1' -2'2' -a1 \
          <(getent group operator | cut -d':' -f3,4                 ) \
          <(getent passwd         | cut -d':' -f1,4 | sort -t':' -k2) \
          | cut -d':' -f3- | tr ',:' ' '
      
  • Keep in mind that UNIX groups are not the only way supplying capabilities. For example:

-1

pw group show ftpgroup

ftpgroup:*:2001:

pw group show wheel

wheel:*:0:root,fred,carl

pw group show video

video:*:44:lightdm

pw user show ftp

ftp:*:2002:2001::0:0:PureFTP user:/nonexistent:/usr/sbin/nologin

pw user show carl

carl:$6$SDkXHtJyIp53egpl$XBg3cuem.RLW63Pa0E16Qw4hmc96lXFgC/fTwCSnDEgYE/OhairDv.mX193ToC6PaQfsp.NegsqEYMHSMxinE/:1003:1003::0:0:Carl Dubak:/home/carl:/usr/local/bin/fish

pw user show fred

fred:$6$alWrCEOtGuU1Bx7t$oWXCNkP4t4yQVn5.0ZKuJqAtCNXkR5ywcdI0Guxqv3myDI.u/qrqUzBX7BW4jmwLFHDd00tCdyGt3A9Q6T4s4/:1002:1002::0:0:Fred Finster:/home/fred:/usr/local/bin/fish

getent passwd {carl}

carl:$6$SDkXHtJyIp53egpl$XBg3cuem.RLW63Pa0E16Qw4hmc96lXFgC/fTwCSnDEgYE/OhairDv.mX193ToC6PaQfsp.NegsqEYMHSMxinE/:1003:1003:Carl Dubak:/home/carl:/usr/local/bin/fish

getent passwd {fred}

fred:$6$alWrCEOtGuU1Bx7t$oWXCNkP4t4yQVn5.0ZKuJqAtCNXkR5ywcdI0Guxqv3myDI.u/qrqUzBX7BW4jmwLFHDd00tCdyGt3A9Q6T4s4/:1002:1002:Fred Finster:/home/fred:/usr/local/bin/fish

id

id=0(root) gid=0(wheel) groups=0(wheel),5(operator)

id 1003

uid=1003(carl) gid=1003(carl) groups=1003(carl),0(wheel),5(operator)

id 1002

uid=1002(fred) gid=1002(fred) groups=1002(fred),0(wheel),5(operator),145(webcamd)

id 5

uid=5(kmem) gid=65533(nogroup) groups=65533(nogroup)

id {operator}

uid=2(operator) gid=5(operator) groups=5(operator)