0

I am supposed to write a shell script that will echo usernames of users whose primary group is equal to the group whose id is the argument of command line.

6
  • Start by breaking it down into subtasks e.g. (1) how to handle command-line arguments in a script; (2) how to obtain a user's primary group from their username (3) how to look up the members of a group. Which part are you stuck at exactly? Commented May 28, 2017 at 19:24
  • 2
    If this an assignment, what command have you learned lately?
    – Jeff Schaller
    Commented May 28, 2017 at 19:24
  • @JeffSchaller hmm I know most of the basic linux commands, I am just not sure how to use them for this problem
    – ivana14
    Commented May 28, 2017 at 19:51
  • If you can show us what you know so far (as it relates to the assignment), then we can provide better answers (that meet your understanding)
    – Jeff Schaller
    Commented May 28, 2017 at 19:54
  • I know that $1 is the argument of the command line, which in my case would be group id. And I understand that I am somehow supposed to find the gid of all the users on my system and then compare those values to $1. I know how to compare and use if, but I just don't know how to get all the users gids. Should I use some kind of a loop or what?
    – ivana14
    Commented May 28, 2017 at 19:57

3 Answers 3

2

Since you're doing the lookup by GID, not by group name, and you're only interested in the primary GID for each user, this is trivially easy with Awk.

The format of /etc/passwd is described in man 5 passwd. To quote the man page:

   There is one entry per line, and each line has the format:

          account:password:UID:GID:GECOS:directory:shell

So you want to print the first field for each line where the fourth field is what is passed in to your script. Where "fields" are delimited by colons.

Personally I wouldn't bother with a script for this; I would use a shell function. See:

So all you need is:

  • An understanding of the -F option for Awk
  • A basic understanding of Awk's syntax, which is condition {action}
  • An understanding of how to reference fields when using Awk, and
  • It will help if you have an understanding of how to pass shell variables to Awk; look into the -v option of Awk.

Check the man page for Awk to get these points.


I won't do your homework for you—the point is to learn to code, not learn to copy and paste. But if you get stuck on this please comment on this question. I can add a bit more detail if needed. (And in a week or so I can update to include a full solution.)


Side note: in the real world, as you can see from the other answers, there is a lot more complexity associated with looking up users. Lots of different ways users can be stored, and accounting for those complexities can be...complex.

But your question appears to be an assignment tailor-made to be easily accomplished with Awk, while also being a realistic application that would be useful in the real world.

2
  • Also see: unix.stackexchange.com/a/254304/135943
    – Wildcard
    Commented May 31, 2017 at 3:25
  • @ivana14, you're welcome! I'd love to see (in a comment here) what you come up with after reading up on the points I mentioned. :)
    – Wildcard
    Commented May 31, 2017 at 11:19
1

That's not always possible because user databases are not always enumerable.

In the passwd database (/etc/passwd, LDAP, mysql, NIS+, etc. or a combination), the primary key is the user name. (several users can have the same uid, possibly with different gids).

You can always query the user database for a given user name, but you can't always retrieve the full list of users.

You can try. There's no standard command for that, but many systems have a getent command which you may be able to use.

getent passwd

Will return the list of users as a csv (colon-separated). The first field is the user name and the fourth the primary gid. So, if you know the gid, you can easily return the list of users using awk.

getent -- group "$group"

Will query the group database for the given $group and will return one line of csv where the third field is the gid. cut would be enough to extract it.

If the user database is not enumerable, you may want to try and query each possible uid numbers individually (beware some systems support uids up to 231), but even then that's not guaranteed to return all possible users as there can be more than one user per uid, and the password database queries usually return only one user.

1
  • 1
    Do what! That first line looks like a comment, not an answer. Commented May 28, 2017 at 22:26
1
#!/bin/sh

if [ $# -ne 1 ]
then
  echo "Usage: $0 gid"
  exit 1
fi

getent passwd | awk -F: -v pgid=$gid '$4 == pgid { print $1 }'

After error-checking for the existence of a parameter, the script then queries the user database (getent passwd) using awk to check the 4th field (primary group id) against the primary group id from the group database. If a line (user entry) matches, it prints the first field (username).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .