2

I wanted to be able to see who is currently logged in into the server and then search /etc/passwd file based on their username and find their ID (column3) and full name (column5) and display them together.

For example:

$ who    
USER         TTY
billyt     pts/2 
$ cat /etc/passwd
…
billyt:x:10:100:Tom Billy:/home/billyt:/bin/bash
…

My output should display his username, ID, and full name:

Username: billyt   ID: 10   FullName: Tom Billy

This is what I tried so far:

#!/bin/bash
file="/etc/passwd"

while IFS=: read -r f1 f2 f3 f4 f5 f6 f7
do
        # display fields using f1, f2,..,f7
        echo "Username: $f1, UserID: $f3, FullName: $f5"
done <"$file"

I tried displaying fields I needed (f1, f3 and f5). Is this a good approach? Will I be able to simply search from who command, save the first field of who (username) to who.txt then search it from the file above?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
endri
  • 57
  • 6
  • You must display your attempted solution. – ooga May 03 '14 at 22:50
  • @ooga sorry forgot to include that. (just did). i tried displaying fields i needed ,f1,f3 and f5. Is this a good approach?will i be able now easily to simply search from who command,save the first field of who(username) to who.txt then search it from the file above? – endri May 03 '14 at 22:55

2 Answers2

3

You can store the users in an array from the who command and then while reading the /etc/passwd file, loop through the array to see if the user is present in the array and if so, print the entries from /etc/passwd file in the format you desire.

Something like:

#!/bin/bash

while read -r user throw_away; do 
    users+=( "$user" )
done < <(who)

while IFS=: read -r f1 f2 f3 f4 f5 f6; do
    for name in "${users[@]}"; do
        if [[ "$name" == "$f1" ]]; then
            echo "Username: $f1, UserID: $f3, FullName: $f5"
        fi
    done
done < /etc/passwd 

We use process substitution <(..) to pass the output of who to first while loop and create an array users. Since we only need the name we use a dummy variable throwaway to capture everything else.

In the second while loop (I re-used most of your existing code), we check if the first field from `/etc/passwd/ file is present in our array. If so, we print the line in your desired format.

You can also also use associative arrays (bash v4.0 or later) to store users as keys. I will leave that to you for practice.

jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • This is just great JS. There is many commands that i wasn't familiar with in your script but thanks to you for the detailed description to each of them, i was able to understand. You must be a genius at least in UNIX. :) Don't know how to thank you enough. – endri May 03 '14 at 23:44
  • 1
    @endri You're welcome and thanks for the kind words. If you have any questions regarding any particular command, please leave a comment and I will try my best to answer. – jaypal singh May 03 '14 at 23:49
  • 1
    @ JS웃 With all pleasure. Your answers are always right and to the point. – endri May 03 '14 at 23:52
1

There are, of course, many ways to do this.

echo "Username     UserID  Full Name"
while read name therest; do
  g=$(grep "$name" /etc/passwd)
  [[ "$g" =~ ([^:]+):[^:]+:([^:]+):[^:]+:([^:]+) ]]
  printf "%-12s %6d  %s\n" \
         "${BASH_REMATCH[1]}" \
         "${BASH_REMATCH[2]}" \
         "${BASH_REMATCH[3]}"
done < <(who)
ooga
  • 15,423
  • 2
  • 20
  • 21