954,525 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Bash Group and User Files

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.

iamthesgt
Junior Poster
107 posts since Nov 2010
Reputation Points: 10
Solved Threads: 0
 

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: [/icode]./script.sh group1 group2 group3 2>/dev/null[/icode]

I hope this helps!

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

Gromit
Posting Whiz in Training
212 posts since Sep 2008
Reputation Points: 47
Solved Threads: 31
 

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
iamthesgt
Junior Poster
107 posts since Nov 2010
Reputation Points: 10
Solved Threads: 0
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: