--- name: getgrnam signature: 'getgrnam NAME' since: 5.0 status: documented categories: ["User and group info"] --- ```{index} single: getgrnam; Perl built-in ``` *[User and group info](../perlfunc-by-category)* # getgrnam Look up a Unix group by name and return its `/etc/group` record. `getgrnam` wraps the C library's `getgrnam(3)`. Given a group name like `"wheel"` or `"staff"`, it returns the matching record from the system's group database — the name, the encrypted password placeholder, the numeric GID, and the list of member login names. Use it when you have a group name in hand and need the GID or the membership list; use [`getgrgid`](getgrgid) for the inverse lookup. ## Synopsis ```perl my ($name, $passwd, $gid, $members) = getgrnam NAME my $gid = getgrnam NAME ``` ## What you get back **List context** yields a four-element list: ```perl my ($name, $passwd, $gid, $members) = getgrnam "wheel"; ``` | Index | Field | Meaning | |-------|------------|-------------------------------------------------| | 0 | `$name` | canonical group name (same as `NAME` on hit) | | 1 | `$passwd` | group password field, typically `"x"` or empty | | 2 | `$gid` | numeric group ID | | 3 | `$members` | space-separated string of member login names | `$members` is a single scalar, **not** an array. Split it yourself when you want a list: ```perl my @logins = split /\s+/, (getgrnam("wheel"))[3]; ``` **Scalar context** yields the numeric GID (the "other thing", since the lookup was by name): ```perl my $gid = getgrnam "wheel"; ``` **No such group**: list context returns the empty list; scalar context returns [`undef`](undef). Test scalar returns for definedness rather than truth — GID `0` (`root`) is a valid hit that is also false: ```perl defined(my $gid = getgrnam $group) or die "no group '$group'"; ``` ## Global state it touches None directly. `getgrnam` is a stateless lookup — unlike [`getgrent`](getgrent), it does not advance the group-database iterator, and [`setgrent`](setgrent) / [`endgrent`](endgrent) do not affect it. It does, however, share the underlying C library's static result buffer with other `getgr*` calls on platforms without thread-safe variants; copy the fields you care about before calling another `getgr*` function. ## Examples Resolve a group name to its GID: ```perl my $gid = getgrnam "wheel"; defined $gid or die "no 'wheel' group on this system"; print "wheel GID = $gid\n"; ``` List the members of a group: ```perl my @fields = getgrnam "staff" or die "no 'staff' group"; my @members = split /\s+/, $fields[3]; print "staff has ", scalar(@members), " members: @members\n"; ``` Use a group name to set the effective GID (requires privilege): ```perl my $gid = getgrnam "video" // die "no 'video' group"; $) = "$gid $gid"; # effective + supplementary ``` Check whether a user is listed as a group member. Note that the primary group (the user's GID in `/etc/passwd`) is **not** in `$members` — check both: ```perl sub in_group { my ($user, $group) = @_; my @g = getgrnam $group or return 0; return 1 if grep { $_ eq $user } split /\s+/, $g[3]; my @u = getpwnam $user or return 0; return $u[3] == $g[2]; # primary group match } ``` Object-oriented form via [`User::grent`](getgrent), which overrides the built-in with a by-name record: ```perl use User::grent; my $g = getgrnam "wheel"; printf "wheel: gid=%d members=%s\n", $g->gid, "@{$g->members}"; ``` ## Edge cases - **Missing group**: list context returns `()`, scalar returns [`undef`](undef). A bare `if (getgrnam $g)` is fine in list context but wrong in scalar context when the GID could be `0`: ```perl if (defined(my $gid = getgrnam $g)) { ... } # correct if (my $gid = getgrnam $g) { ... } # wrong for GID 0 ``` - **Members is a string, not a list**. Forgetting this and writing `scalar @members = getgrnam $g` (or indexing `$members[0]`) silently gives wrong results. Always `split /\s+/` the fourth field. - **Primary-group members are absent from the list**. A user whose `/etc/passwd` GID matches the group is a member in the kernel's eyes but will not appear in `$members`. Lookups that classify users by group must consult [`getpwnam`](getpwnam) too. - **Password field is not a password**. On every modern Linux the second field is `"x"` (shadow redirection) or empty. It is never the plaintext or hash of a group password. Do not rely on its format. - **Case sensitivity**: group names are case-sensitive on Linux. `getgrnam "Wheel"` does not find `wheel`. - **Name with embedded whitespace or colon**: the group database format does not allow either, so such names cannot exist; the lookup simply fails. - **NSS backends**: on systems configured with LDAP, SSSD, or other name-service switch modules, `getgrnam` consults those as well as `/etc/group`. Results therefore depend on `/etc/nsswitch.conf` and the configured backends, not on `/etc/group` alone. - **Taint**: the fields come from outside the program, so under `-T` they are tainted and must be laundered before use in sensitive operations. - **Thread safety**: pperl automatically substitutes the thread-safe `getgrnam_r` when the platform provides it. On platforms without it, concurrent `getgr*` calls across threads can clobber each other's results. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`getgrgid`](getgrgid) — inverse lookup by numeric GID; reach for this when you have the GID and want the group name or member list - [`getgrent`](getgrent) — iterate every group in the database when you do not know the name or GID in advance - [`setgrent`](setgrent) — rewind the [`getgrent`](getgrent) iterator to the start of the group database - [`endgrent`](endgrent) — close the group-database file descriptor opened by iteration - [`getpwnam`](getpwnam) — the parallel call for the user database; use alongside `getgrnam` when you need to resolve a user's primary group - `User::grent` — object-oriented wrapper that overrides `getgrnam` to return a record object with named accessors (`name`, `passwd`, `gid`, `members`) instead of a positional list