--- name: getgrgid signature: 'getgrgid GID' categories: ["User and group info"] status: documented --- ```{index} single: getgrgid; Perl built-in ``` *[User and group info](../perlfunc-by-category)* # getgrgid Look up a group record by numeric group ID. `getgrgid` asks the system group database for the entry whose `gid` is `GID` and returns what it finds. It is the numeric counterpart of [`getgrnam`](getgrnam) and mirrors the C library call `getgrgid(3)`. In list context you get the unpacked record fields; in scalar context you get the group name. ## Synopsis ```perl my ($name, $passwd, $gid, $members) = getgrgid($gid); my $name = getgrgid($gid); ``` ## What you get back In **list context**, four values unpacked from `struct group`: ```perl # 0 1 2 3 my ( $name, $passwd, $gid, $members ) = getgrgid($gid); ``` - `$name` — the group name. - `$passwd` — the group password field. On modern systems this is typically `"x"` or empty; real hashes live in a shadow database. - `$gid` — the numeric group ID (the same number you passed in, echoed back from the record). - `$members` — a **single space-separated string** of member login names, not a list. Split it yourself when you need an array: ```perl my @users = split / /, (getgrgid($gid))[3]; ``` In **scalar context**, just the group name: ```perl my $name = getgrgid(0); # "root" on most Linux systems ``` If no group with the given `GID` exists, the function returns the empty list in list context and [`undef`](undef) in scalar context. A system-level failure (e.g. NSS backend unreachable) is reported the same way; check [`$!`](../perlvar) if you need to distinguish. ## Global state it touches - [`$!`](../perlvar) — set on system-level failure of the underlying `getgrgid(3)` call. Not set when the `GID` simply has no matching entry; that is a normal "not found", not an error. - The process-wide group-database iteration cursor maintained by libc. `getgrgid` does **not** advance or reset the cursor used by [`getgrent`](getgrent), [`setgrent`](setgrent), and [`endgrent`](endgrent), but it shares the same underlying file descriptor on most implementations — interleaving direct lookups with iteration is portable in theory and surprising in practice. ## Examples Look up the primary group name for the current process: ```perl my $group = getgrgid($(); # $( is the real GID print "running as group: $group\n"; ``` Resolve a file's group ID to a name, with a sensible fallback for orphaned GIDs (files owned by a group that no longer exists): ```perl my $gid = (stat $file)[5]; my $name = getgrgid($gid) // ""; ``` Unpack the full record and list the members: ```perl if (my ($name, undef, $gid, $members) = getgrgid(100)) { my @users = split / /, $members; print "group $name ($gid) has ", scalar(@users), " members\n"; } ``` Guard against the "no such group" case explicitly — the empty list in boolean/list context is already falsy, so an `if` suffices: ```perl unless (my @gr = getgrgid($gid)) { die "no group with gid $gid\n"; } ``` Pair with [`getpwuid`](getpwuid) to render a directory listing's owner and group columns: ```perl my @st = stat $path or die "stat $path: $!"; my $user = getpwuid($st[4]) // $st[4]; my $grp = getgrgid($st[5]) // $st[5]; printf "%-8s %-8s %s\n", $user, $grp, $path; ``` ## Edge cases - **Scalar vs list context matters.** `getgrgid($gid)` in scalar context yields only the group name; wrap in parentheses or assign to a list to get the full record: ```perl my $name = getgrgid(0); # "root" my @record = getgrgid(0); # four-element list my $gid_out = (getgrgid(0))[2]; # the gid field ``` - **`$members` is a string, not an array.** The whitespace-joined form is historical and matches perl5's `pp_gpwent` / `pp_ggrent` output. Splitting on `/ /` (single space) is the canonical idiom; splitting on `/\s+/` is slightly more forgiving if a backend ever uses tabs. - **Empty groups** return `$members` as the empty string. `split / /, ""` yields the empty list, which is what callers usually want. - **Numeric coercion.** `GID` is passed to the C call as an integer. A non-numeric scalar is coerced: `"0root"` becomes `0`. Pass a clean integer. - **GID namespace overlap.** Multiple group entries with the same `gid` are legal in `/etc/group` and in NSS. `getgrgid` returns **one** of them — which one is backend-defined. Do not rely on which name comes back when GIDs collide; use [`getgrnam`](getgrnam) for the reverse direction when the name matters. - **NSS / nsswitch.conf.** The lookup follows the system's name service switch — `files`, `sss`, `ldap`, etc. A successful lookup in a test harness on one host may fail on another with a different NSS configuration. This is a property of the C library, not of Perl. - **Large groups.** Very large group-member lists (hundreds of members) can arrive truncated if the backend's internal buffer is smaller than the rendered line. This is a libc / NSS limitation; Perl faithfully surfaces whatever the system returned. - **Threaded builds.** On systems that provide `getgrgid_r`, perl transparently calls the reentrant variant. Callers see no difference. - **Taint.** Under `-T`, `$passwd` and `$members` come back tainted — the first because it may encode credentials, the second because administrators can change it. `$name` and `$gid` are not tainted. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`getgrnam`](getgrnam) — the inverse lookup: group record by name rather than by `gid` - [`getgrent`](getgrent) — iterate every group entry when you need to scan rather than look up - [`setgrent`](setgrent) and [`endgrent`](endgrent) — reset and release the iteration cursor used by [`getgrent`](getgrent) - [`getpwuid`](getpwuid) — the passwd-side counterpart; pair with `getgrgid` to render owner/group columns - `User::grent` — by-name accessor object that overrides `getgrgid` when you prefer `$gr->name` over positional unpacking