Search code examples
linuxbashif-statementgrepuser-input

Operators and user input not found / unexpected while checking if users and groups exist in /etc/group and /etc/passwd


I can't understand what's wrong with my code. I'm trying to make it so that if the passed in username and group are both not found in /etc/group and etc/passwd echo both not found.

If one but not the other is found echo one is found and finally if they are both found then echo both exist.

Here is my code:

#/bin/bash

read -p 'Username: ' username
read -p 'Group: ' group

if [ $(grep "^$group:" /etc/group | cut -f 1 -d ':') != $group ] && [ $(grep "^$username:" /etc/passwd | cut -f 1 -d ':') != $username ]
then 
  echo Both not found 

elif $(grep "^$group:" /etc/group | cut -f 1 -d ':') != $group ] || [ $(grep "^$username:" /etc/passwd | cut -f 1 -d ':') != $username ]
then
  echo One exists, one does not.

elif $(grep "^$group:" /etc/group | cut -f 1 -d ':') = $group ] && [ $(grep "^$username:" /etc/passwd | cut -f 1 -d ':') = $username ]
then
  echo both exist
fi

Here is the output:

$ ./exercise_10.sh        
Username: user
Group: root
./exercise_10.sh: 10: root: not found
./exercise_10.sh: 14: root: not found
                                                                                                                                                                               
$ ./exercise_10.sh
Username: dfgdfggd
Group: root
./exercise_10.sh: 10: root: not found
./exercise_10.sh: 10: [: !=: unexpected operator
./exercise_10.sh: 14: root: not found
                                                                                                                                                                               
$ ./exercise_10.sh
Username: dfgdg
Group: cgdgdfg
./exercise_10.sh: 6: [: !=: unexpected operator
./exercise_10.sh: 10: !=: not found
./exercise_10.sh: 10: [: !=: unexpected operator
./exercise_10.sh: 14: =: not found

I've tested the grep and cut command in the command line and it works:

$ grep '^user:' /etc/passwd | cut -f 1 -d ':'
user

Solution

  • There is a missing ! in the shebang, the first line should be:

    #!/bin/bash
    

    There are missing [ right after the elifs.

    You could always use shellcheck command to parse and list all issues in a bash script:

    shellcheck ./exercise_10.sh
    

    Finally you could rely on grep command return status with if statements like the one below:

    if grep -q "^${group}:" /etc/group 2>/dev/null && grep -q "^${username}:" /etc/passwd 2>/dev/null ; then
      printf "Both exist.\n"
    ...
    

    Give a try to this, which only parse each file once:

    #!/bin/bash
    
    read -rp 'Username: ' lusername
    read -rp 'Group: ' lgroup
    
    if grep -q "^${lgroup}:" /etc/group 2>/dev/null ; then
      if grep -q "^${lusername}:" /etc/passwd 2>/dev/null ; then
        printf "Both exist\n"
      else 
        printf "One exists, one does not\n"
      fi
    else
      if grep -q "^${lusername}:" /etc/passwd 2>/dev/null ; then
        printf "One exists, one does not\n"
      else
        printf "Both not found\n"
      fi
    fi