How to List All Users in Linux

Operating systems based on the Linux kernel support multiple user accounts. Instead of "user accounts" they're often just called "users".

So let's see how to list all of these users / accounts. First, we'll explore the commands. And at the end of this blog we'll explain how the commands work.

List All Users on Linux

To list all the users on a Linux machine, we can run this command:

getent passwd | awk -F: '{ print $1 }'

We'll get a result like this:

Screenshot showing how to list all Linux user accounts with the "getent" command

This list is quite long. Do we really have so many user accounts on our system? Which person will log in as the user called "www-data" on this machine?

Well, no actual human being will log in as "www-data". But a program like the Apache web server will use that account to do some of its work.

Which means some of these users / accounts are meant to be used by programs. And others are meant for actual human beings. Linux-based operating systems call these:

  1. System accounts.
  2. User accounts.

If we're not interested in system accounts, we can filter our output this way.

List Regular (Non-System) User Accounts on Linux

To list just regular user accounts on a Linux system (accounts that are normally used by people), we can run this command:

getent passwd | awk -F: '($3>999){ print $1 }'

Now the output will be much shorter:

Screenshot showing how to list regular user accounts on Linux

List Users that Belong to a Certain Group on Linux

On a system with many user accounts we might want to filter based on groups. Otherwise said, show only those users that belong to a certain group.

For example, maybe we want to see which users have administrative privileges. To do that, we can list users belonging to the "sudo" group:

getent group sudo | awk -F: '{ print $4 }'

And we'd get a list of usernames, separated by a , comma character:

Screenshot showing how to list users that belong to a certain group, on Linux

If you're interested in users that belong to a different group, just replace sudo , in the command above, with the group name you require.

Explaining the Commands

Now let's break down all of these commands, and see how they work.

First, when we listed all users on Linux we ran:

getent passwd | awk -F: '{ print $1 }'

Why is that? Well, let's explore the first part of the command.

Understanding the 'getent passwd' Command

Linux-based operating systems store a lot of the information they need in simple text files. So when you need to get information about users / accounts on a system, many people will recommend a command like:

cat /etc/passwd

Which will display the /etc/passwd file, where Linux stores info about users / accounts.

Screenshot showing how to list all user account information stored in the "/etc/passwd" file

And sure enough, it works… most of the time. But not always!

That's why we used getent passwd instead. Which seems to show us the same thing as the cat /etc/passwd command:

Screenshot showing how to list all user account information with the "getent" command

So, why getent passwd? Because, in some cases, user / account information might not be stored entirely in the /etc/passwd file. On some systems – for example those that use LDAP – some user information can be stored on a separate server.

Which means, you will get some user information from the /etc/passwd file. But not all of it. Because some user accounts will be defined on a separate server, somewhere. So taking a look at the /etc/passwd file might only give you partial data. While getent passwd will show you the full picture:

  • User data stored locally, in files like /etc/passwd.
  • But also user data stored on LDAP servers, or other remote places. (As long as the Linux machine is configured to use those as sources for additional user accounts).

Now, you might notice: The getent passwd command shows us a lot of data:

Screenshot showing how to list all user account information with the "getent" command

Useful when you need all information about users / accounts. Such as: Number IDentifiers (IDs), what their home directories are, what shell program each account uses, and so on.

But when all you need is just a list of users / accounts, then the normal output of getent passwd is quite messy.

That's why we needed the second part in our command: awk -F: '{ print $1 }'. And how we ended up with:

getent passwd | awk -F: '{ print $1 }'

Let's explore that second part.

Filtering Output with awk to Show Just the Usernames

A command like

getent passwd

shows us this:

But,

getent passwd | awk -F: '{ print $1 }'

cleans up that output and shows us this:

Screenshot showing how to use the "awk" command to filter just the usernames from the output of the "getent passwd" command

This is called piping output to another command. Essentially, we:

  • Take the (messy/overloaded) output from the getent passwd command.
  • And send it to a second command: awk -F: '{ print $1 }'. Which cleans up the output from the first command.

Think of awk as a "programming language" that processes text. It helps you extract what you need, and / or transform the text / reformat it to something else.

Now let's understand how this part works:

awk -F: '{ print $1 }'

The command:

getent passwd

displays output like this:

Screenshot showing the type of output displayed by the "getent passwd" command

Notice the format. We can see a user name like root, followed by the : character, then some other data fields. Each field is separated by this : character.

The first thing we do in:

awk -F: '{ print $1 }'

We tell awk that what separates these fields is the : character. That's the purpose of -F:.

Then, we specify the "program" / instruction that awk should run: print $1. Which tells awk: "Print the first field". If we'd want to print the second field, we'd write $2. But we're interested in the first field, since that's where the username is located on each line, in our output.

This print $1 instruction is wrapped between { } curly brackets, since that's the syntax that awk expects. And, finally, we also wrap the curly brackets between ' ' single quotes. That's just to prevent our shell / command interpreter from misinterpreting what we wrote here. It's a way to tell our Bash shell:

"Look, about this thing wrapped between single quotes: It's for the awk program, it's not for you. Please literally send this to the program, and don't try to interpret it / transform it in any way before doing that. Just send this text as I wrote it, don't interfere!"

So, wrapping all that up, we end up with this command:

getent passwd | awk -F: '{ print $1 }'

Which:

  • Retrieves all user information available, with getent passwd.
  • Sends (| pipes) the output to awk.
  • Tells awk that the field separator is :.
  • And then instructs awk to print just the first field (the username, in this case).

And we get the output we needed:

Screenshot showing how to filter "getent passwd" output with "awk" command, to only show list of usernames

Now let's explore the command that filters only non-system users / accounts. That works almost the same way, but it uses an additional awk trick.

Filtering Output with awk to Show Only Non-System Accounts

To display only accounts meant for human beings, we used this command:

getent passwd | awk -F: '($3>999){ print $1 }'

Which showed us this output:

Screenshot showing how to filter "getent passwd" output with "awk" command to only show regular (non-system) user accounts on Linux

We can see we used the same tricks:

  • We | piped getent passwd output to the awk program.
  • We told awk what the field separator is.
  • We instructed awk to print the first field.

But, we have an additional trick in there: ($3>999).

This essentially adds a condition to awk, telling it:

"Only show me output where the third field ($3) contains a value LARGER than (>) 999. So, anything from 1000, and up."

Why? Because the getent passwd command outputs lines like these:

alex:x:1000:1000:alex:/home/alex:/bin/bash

lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false

nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

polkitd:x:998:998:User for polkitd:/:/usr/sbin/nologin

john:x:1001:1001:,,,:/home/john:/bin/bash

Note the third field on all lines. That's the user ID, a number uniquely identifying each user / account. And note that only "alex", "john", and "nobody" have an user ID larger than 999. One is 1000, one is 1001, and one is 65534. So only these three users will match the rule sent to awk: "Third field has to be larger than 999."

That's why:

getent passwd | awk -F: '($3>999){ print $1 }'

will display this output:

Screenshot showing how to filter "getent passwd" output with "awk" command to only show regular (non-system) user accounts on Linux

Now you might ask: "But wait! Why does anything with an ID larger than 999 have any special meaning?" Well, that's just common practice on most Linux systems. By default, the system is configured so that:

  • Any user account will be assigned an ID that is equal to 1000, or larger than 1000.
  • Any system account will be assigned an ID that is smaller than 1000. Usually, anything with an ID between 100 and 999.

These settings for the IDs are defined in the /etc/login.defs file. Some Linux distributions might make some adjustments to these defaults.

Hopefully, this demystified all the concepts we used in these commands. If not, ask away in the comments.

💡
Note: The first version of this blog showed commands like:
getent passwd | awk --field-separator=: '{ print $1 }'

But --field-separator only works with the gawk utility (included by default on Ubuntu distributions). However, Debian uses mawk , by default. And the mawk utility does not understand the --field-separator option. So--field-separator=: was replaced with -F: throughout this blog. To make sure it works on both Ubuntu, Debian, and most of the other popular Linux distributions.

Reference for awk commands: