-1

Kinda stuck here, did not found any solutions.

Check If user exist in /etc/passwd, If exist create new one with prefix new_the_existed_one

#!/bin/bash

myuser="/home/yakyak/Desktop/Exercises/newusers.txt"

sed '/^[ \t]*$/d' $myuser | while read -r line do name="$line" # adduser --disabled-login --gecos "" $name # check if user exist isthere=$(cut -d: -f1 /etc/passwd | grep "$name")

    # if user was added then make insert record into log file
    if [[ "$isthere" == "$name" ]]
    then
        echo "User already exist, creating new user.."
        adduser --disabled-login 
    # adduser --disabled-login --gecos " " $name
    fi   

done

muru
  • 72,889
YakyAK
  • 13
  • 1
    How does newusers.txt look like? Where exactly are you stuck - please try to describe your problem in more detail. In your script: what part does work well, where does it fail? – FelixJN Jan 27 '22 at 01:52
  • 2
    don't grep /etc/passwd directly, use getent instead. e.g. getent passwd "$name" | cut -d: -f1. Also, your isthere variable isn't needed at all, you can test the exit code of getent directly. if getent passwd "$name" > /dev/null ; then ..... ; fi. Or, if you insist on grepping /etc/passwd directly because you've never heard of getent before and it's confusing and scary: if grep -q "^$name:" /etc/passwd ; then ... ; fi but you shouldn't do that, you should learn the right tool for the job. – cas Jan 27 '22 at 04:23
  • 1
    BTW that grep -q should only be used if $name has been sanitised so that it doesn't contain any regex special characters like . or *. or use grep -Pq "^\Q$name\E:" /etc/passwd (using perl regex \Q and \E to disable regex metacharacters in $name). But you should still use getent instead of grepping /etc/passwd. – cas Jan 27 '22 at 04:28
  • What if the user does not exist - create one with name from newusers.txt? – RudiC Jan 27 '22 at 08:14
  • Thanks everyone for your assistance I have a text file with users under the name newusers.txt, I want to check if the user exist in /etc/passwd, If the user exist create a new user with new_existed_username, Struggling with this. – YakyAK Jan 27 '22 at 09:44

1 Answers1

1
#!/bin/bash

NAME_REGEX='^[a-z][-a-z0-9]*$'   # default value for adduser.conf
. /etc/adduser.conf              # "source" it in case local config is different

myuser='/home/yakyak/Desktop/Exercises/newusers.txt'

grep "$NAME_REGEX" "$myuser" | while read -r name; do
  while getent passwd "$name" > /dev/null; do
    name="new_$name"
  done

  # check if $name is > 32 characters
  if [ "${#name}" -gt 32 ] ; then
    echo "username '$name' is too long" > /dev/stderr
  else
    adduser --disabled-login --gecos '' "$name"
  fi
done

Instead of using sed to delete empty lines from your newusers.txt file, it uses grep to exclude invalid usernames, those which don't match a pattern stored in a shell variable called $NAME_REGEX. It uses the same variable name (and regex pattern) as adduser itself for the definition of "valid". See man adduser.conf and search for NAME_REGEX.

This will keep on pre-pending "new_" to $name until $name doesn't exist in the passwd db. If "user" exists, it'll try "new_user". if "new_user" exists, it'll try "new_new_user". and then "new_new_new_user". and so on.

The script uses getent passwd, but only cares about the exit code - the output is discarded (redirected to /dev/null). If getent exits with 0 (true), then the user exists, so try again.

When getent returns false (i.e. $name doesn't already exist), it checks if the name is too long. If it is, it prints an error message. If it isn't, it runs adduser.

BTW, the actual exit code we expect to see from getent is 0 for if the user already exists and 2 if the user does not exist. In some circumstances, getent can return different exit codes (see man getent), but they're not possible with the way we're using getent (i.e. searching the passwd db AND providing a username).


A slightly better version would be to use a numeric suffix for the usernames. e.g. using printf with a %03i format string for a 3-digit wide zero-padded number (e.g. 001, 002, etc). If you don't want it zero-padded, use %i instead. The count variable is reset to zero in the outer while loop for each username processed.

#!/bin/bash

NAME_REGEX='^[a-z][-a-z0-9]*$' # default value for adduser.conf . /etc/adduser.conf # "source" it in case local config is different

myuser='/home/yakyak/Desktop/Exercises/newusers.txt'

grep "$NAME_REGEX" "$myuser" | while read -r user; do name="$user" count=0

while getent passwd "$name" > /dev/null; do let count+=1 name="$(printf "%s%03i" "$user" "$count")" done

check if $user is > 32 characters

if [ "${#name}" -gt 32 ] ; then echo "username '$name' is too long" > /dev/stderr else adduser --disabled-login --gecos '' "$name" fi done

This version uses two variables for the username - $user for the name as read in from the newusers.txt file, and $name for the current username we're trying to use. $name is initially copied from $user, and the inner while loop updates $name by incrementing the $count variable and appending it to $user whenever getent returns true.


Finally, neither of the above are particularly good scripts. They do little more than the bare minimum required. Personally, I'd be inclined to write it in perl rather than bash because text processing in shell is a PITA.

cas
  • 78,579