Some Linux tools for handling and filtering the passwd file

Linux (and other Unixes) store user information in a file called passwd and the associated passwords in another file called shadow, both located in /etc. Both files are text files and use a : as the field separator.

I currently have the need to sort and filter these files in various ways. This post is mostly so I can look it up later, but if it is useful for others, you’re welcome.

WARNING: Be very careful when modifying these files. If you make a mistake, you could damage your system. It’s possible to lock out even the root user when doing this.

  • Always back up these files first. Also make a note of the permissions that have been applied to them.
  • Ensure that a separate root console is active/logged in, either on a different virtual console or in a separate SSH session. Do not log out until you are certain that you can log in again.

Having said that, it should be noted that the subsequent commands do not alter the files in any way, making them safe to use as long as the output is not redirected to overwrite these files.

Sort the passwd file by the user id

The user id is stored in the 3rd field of the file and it is numeric:

sort --numeric --field-separator=: --key=3 passwd

Filter computer accounts from passwd and shadow

If the computer is used as the domain controller for a Samba NT4 domain, the files contain entries for all computers in the the domain. The user name for these entries ends in a dollar sign “$”. So we need a regular expression that excludes all these entries.

grep -v "^[^:]*\$:" passwd
grep -v "^[^:]*\$:" shadow

Filter system users from passwd

On a Linux system there are many system accounts that are used for special purposes, e.g. for the web server, email or backup. These accounts have a user id < 1000 (this might be some specialty of Ubuntu Linux). We only want lines where the user id has 4 digits. We also must be sure that these 4 digits are in the user id field, so we have to anchor the regex on the start of the line and skip the name and password (always "x") field.

egrep "[^:]:x:[0-9]{4}:" passwd

(On servers with very many users, there may be user ids with more than 4 digits, but that doesn’t currently concern me.)

Filter non-system users from passwd

This is the opposite of the above. It only retains the users with user ids < 1000, which means the lines where the user id has 1 to 3 digits. Again, we have to make sure to filter the user id field and none of the others.

egrep "[^:]:x:[0-9]{1,3}:" passwd