#!/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.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/etc/passwd
directly, usegetent
instead. e.g.getent passwd "$name" | cut -d: -f1
. Also, youristhere
variable isn't needed at all, you can test the exit code ofgetent
directly.if getent passwd "$name" > /dev/null ; then ..... ; fi
. Or, if you insist on grepping /etc/passwd directly because you've never heard ofgetent
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:23grep -q
should only be used if$name
has 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. – cas Jan 27 '22 at 04:28newusers.txt
? – RudiC Jan 27 '22 at 08:14