This is homework. I was writing a bash script that accepts a list of group names on the command line and produces a group report detailing the group id and the number of group members identified in /etc/passwd for each group. Output will look like:
Group Report
Group GID Count
------ ----- ------
css 301 439
faculty 300 78

To try and get this, I use several loops to go through the files and if statements as comparisons. Here is my code:

#!/bin/bash

FILENAME=/etc/passwd
FILENAME2=/etc/group
UIDMAX=1000

echo -e "\tGroup Report"
echo
echo "Group    GID    Count"
echo "------- ------- -------"
for g in "$@";
  do
    for groupname in [$(cut -d: -f1 $FILENAME2)];
      do
        if [ "$@" == "$groupname" ]
           then
              GID=[ cut -d: -f3 $FILENAME2 ]
              for grpid in [$(cut -d: -f4 $FILENAME)];
                 do
                     Count=0
		     uidtest=[ cut -d: -f3 $FILENAME ]
		     if [[ "$uidtest" -gt "$UIDMAX" ]]
			then
	   		     if [ $GID=$grpid ]
				then 
		                    Count=`expr $Count + 1`
		             fi
		     fi
                 done
               echo "$groupname    $GID    $Count"
        fi
      done
   done

However, it iterates through the files and outputs most of the group ids. Here is the output if I run with the argument "adm" (a group that has one member on my machine (me)):

Group Report
Group    GID    Count
------   -----  ------
0
1
2
3
4
5
6
7
8
9
10
13
33
34
38
39
41
65534
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
1000
115
cut: ]: No such file or directory
adm        0

It does that several dozen times - exact same output of the numbers and the last two lines (error message, group name). I didn't bother posting all the rest of the output, as it seems to do it every time the for loop for grpid in [$(cut -d: -f4 $FILENAME)]; runs.
If anyone could point out what I'm doing wrong, that would be great.

Recommended Answers

All 2 Replies

Hi!

It looks like you're off to a good start! Since it's homework, I won't make any suggestions about doing it a different way, but I can point out some things that I can definitely see that might trip you up in the troubleshooting process!

First: when you want to execute a command and do something with the output, don't use [square brackets], just use the $(commands go here) style. Square brackets indicate that you want to do some kind of evaluation (true/false) of the output.

Second: you go to the trouble of setting the "$g" variable, but then you call "$@" again a few lines down, when I assume you just want to work with one value of $@ per loop. Try using "$g" in your evaluation of "if $groupname=$g".

Third: This is the real clue to what's happening, I think! You're working with cut, which is giving you whole columns of data, but you really only need one row out of that column of data for each iteration of "$g". Try using 'awk' or 'grep' to narrow down the results ;)

Once you've tweaked those three things, I think you'll be much closer to a working script. I'm not sure about the logic in the loop where you're calculating $count, but I think when you resolve the three things above, the rest should be easier to sort out.

One more hint... all those numbers might be getting printed to stderr instead of stdout... try redirecting stderr to /dev/null, and it could help you see what's actually working a little more clearly! example:

./script.sh group1 group2 group3 2>/dev/null

I hope this helps!

P.S. - try running your script with "bash -x" for debugging output!

commented: Thanks for the help. +3

Thanks. I was having problems with the cut outputting whole columns of data like you said, so since I was already using loops I just read the whole files into arrays and cut from each array entry. Here is the completed bash script:

#!/bin/bash

FILENAME=/etc/passwd
FILENAME2=/etc/group
UIDMAX=999

echo -e "\tGroup Report"
echo
echo "Group    GID    Count"
echo "------- ------- -------"

index=0
while read line; do
etcgroup[$index]="$line"
index=$(($index+1))
done < $FILENAME2

index2=0
while read line; do
etcpasswd[$index2]="$line"
index2=$(($index2+1))
done < $FILENAME

for g in "$@";
  do
    Count=0
    for ((i = 0 ; i < $index ; i++)); do
	grp=${etcgroup[$i]}
	grpnm=$(echo $grp | cut -d: -f1)
        grpid=$(echo $grp | cut -d: -f3)
	if [ "${g}" == "$grpnm" ]
	    then
	      GID=$grpid
	      for ((j = 0 ; j < $index2 ; j++)); do
		  pass=${etcpasswd[$j]}
		  usrid=$(echo $pass | cut -d: -f3)
		  passgid=$(echo $pass | cut -d: -f4)
		     if [ "$passgid" == "$grpid" ]
			then
			    if [[ "$usrid" -gt "999" ]]
				then
				    Count=`expr $Count + 1`
			    fi
		     fi
	      done
	        echo -e "$grpnm\t $GID\t$Count"
	fi
    done
done
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.