Read Linux User and Group IDs Reliably with id
Scripts that trust whoami eventually break, which is why id exists: it reads the real user and group IDs behind any account. This guide covers the current process, a named account, numeric versus name output, and group membership without surprises from the default format. The examples use GNU coreutils 9.4, the version installed on the machine used here.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a shell and the GNU id command, normally installed with the coreutils package. No elevated privileges are needed for anything below. Allow about five minutes to run the examples and compare them with your own account.
Checkpoint
Confirm the version before relying on any behaviour in a script.
$ id --version
id (GNU coreutils) 9.4
The version number may differ on another distribution. The option meanings used here belong to the GNU command documented by the local manpage.
1. See the current process identity
Run id with no options. It reports the current process: user ID, primary group ID, and supplementary groups, with names in parentheses after the matching numbers.
$ id
uid=1000(alice) gid=1000(users) groups=1000(users),27(sudo),987(docker)
Your numbers and names will differ. The part before the first group is the user identity. gid is the effective primary group. The groups list includes that group plus any supplementary groups available to the process.
This is a diagnostic command, not a membership editor. It does not add the account to a group or change the process identity.
2. Ask for one identity at a time
Use the short options when another command needs a single value. Each of these writes only the requested value followed by a newline:
$ id -u
1000
$ id -g
1000
$ id -G
1000 27 987 1001
| Command | Result | Typical use |
|---|---|---|
id -u | Effective user ID | Pass a numeric owner to a tool or script |
id -g | Effective group ID | Check the process's primary group |
id -G | All group IDs | Inspect supplementary group membership |
Checkpoint
If a script needs one number, use id -u or id -g, not the human-readable default line. That skips having to parse labels and parentheses.
3. Choose names, real IDs, or effective IDs
Add -n to -u, -g, or -G when names are more useful than numbers.
$ id -n -u
alice
$ id -n -g
users
$ id -n -G
users sudo docker alice
The -r option asks for the real ID instead of the effective ID. It matters most in a program that has changed identity, such as a set-user-ID program. Combine it with the selector:
$ id -r -u
1000
$ id -n -r -u
alice
Do not read -r as "the account that originally logged in". It asks the operating system for the real user or group ID tied to the process. Without -u, -g, or -G, the default report is used instead.
4. Inspect a named account
Pass a user name to see that account's identity rather than the current process. This reads account and group information; it does not switch users and does not run a command as that account.
$ id root
uid=0(root) gid=0(root) groups=0(root),994(kvm),986(ollama)
Options can be combined with a name when you need a machine-friendly value:
$ id -u root
0
$ id -n -g root
root
If the account does not exist, id prints an error and exits with status 1.
$ id definitely-no-such-user
$ echo $?
1
In a script, test the exit status rather than assuming an empty or partial result means "not found". Quote a user name that comes from a variable before passing it to the shell, and treat account names as data.
5. Make group output safe for a pipeline
id -G separates group IDs with spaces. For predictable processing, id -z -G separates them with NUL characters instead, which is useful once the next tool accepts NUL-delimited input and you do not want whitespace mistaken for a separator.
$ id -z -G | od -An -t x1
31 30 30 30 00 32 37 00 39 38 37 00
The 00 bytes are the delimiters. The -z form is not permitted with the default, descriptive output, so pair it with a selector such as -G. Do not pipe this form into a command that expects ordinary text lines unless you deliberately want NUL bytes.
Common traps and boundaries
- Primary is not all.
-ggives one effective group ID, while-Ggives the complete group list. - Names are not stable identifiers. Names can change or be unavailable in a minimal environment. Use numeric output when storing or comparing identity values.
- Shell substitution is not validation. Check
id's exit status before using its output, especially when the account name comes from input. - SELinux is separate.
id -Zrequests only the security context. On a system without an SELinux-enabled kernel it reports the operation is unavailable; it does not enable SELinux. - No undo is required. Every command in this guide only reads identity information. If you expected group changes, use your distribution's account-management tools, then start a new session where appropriate; those changes require separate, elevated administrative steps.
Done means
- Read the default report. You can read the user, primary group, and supplementary groups from plain
id. - Selected single values. You can pull numeric or named user and group values with
-u,-g,-G, and-n. - Told real from effective. You can distinguish real IDs from effective IDs with
-r. - Handled edge cases. You know how to check a named account's failure status and use NUL-delimited group output safely.