#!/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.
newusers.txtlook 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?/etc/passwddirectly, usegetentinstead. e.g.getent passwd "$name" | cut -d: -f1. Also, youristherevariable isn't needed at all, you can test the exit code ofgetentdirectly.if getent passwd "$name" > /dev/null ; then ..... ; fi. Or, if you insist on grepping /etc/passwd directly because you've never heard ofgetentbefore and it's confusing and scary:if grep -q "^$name:" /etc/passwd ; then ... ; fibut you shouldn't do that, you should learn the right tool for the job.grep -qshould only be used if$namehas been sanitised so that it doesn't contain any regex special characters like.or*. or usegrep -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.newusers.txt?