-2

I am looking to add multiple users to a UNIX Red Hat system. I am using two text files as sources containing 9 usernames and 9 full names separated individually on 9 new lines.

$U contains usernames.txt, $I contains fullnames to go with the -c command and $Z contains the ending numbers from 1-9 to set the -u ending value. What I hoped the script would achieve is that it would populate the useradd command with the values I outlined to make the useradd command execute adding users with their username, comment field (full name) and an ID value. I used an echo command to test what the output was before actually executing the useradd command part of the script on the system. However, the script actually interpreted the spaces in the fullnamecomment.txt as separate iterations and basically the script prints out the same query 9 times sequentially adding 1 to the -u value.

@Community, can anyone provide any input on optimizing this script or changing my method to add multiple users populating username, comment and ID values within the useradd command?

Thanks.

#!/bin/bash

for U in $(cat username.txt)
do
        for I in $(cat fullnamecomment.txt)
        do
                for Z in {1..9}
                do
                        #useradd $U -m -c $I -u 10010$Z
                        echo "useradd $U -m -c $I -u 10010$Z"
                done
        done
done
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 2
    [DontReadLinesWithFor](https://mywiki.wooledge.org/DontReadLinesWithFor) – Charles Duffy Sep 21 '21 at 19:19
  • 1
    Also, if you want the first line from `username.txt` to match with the first line of `fullnamecomment.txt`, the 2nd line of each file to match with the 2nd line of the other, etc., you shouldn't be using a nested loop at all. If that _is_ what you're trying to do, specify it clearly, and I can dig up an existing asked-and-answered question describing the technique. – Charles Duffy Sep 21 '21 at 19:24
  • BTW, to show your own modification to someone's answer, add your own answer with the Add An Answer button instead of editing answers into the question. See discussion on [meta.se], including [What to do when OP answers his/her own question in an edit?](https://meta.stackexchange.com/questions/74101/what-to-do-when-op-answers-his-her-own-question-in-an-edit) and [Should I update my question to include the correct answer?](https://meta.stackexchange.com/questions/41700/should-i-update-my-questions-code-to-include-the-correct-answer) – Charles Duffy Sep 21 '21 at 20:28
  • Thanks Charles! I have updated my question and added an answer with modifications to SteveKlines resolution to make it work on my system. Thanks to CharlesDuffy and SteveKline for taking the time to respond. Much appreciated! I hope to answer one of your questions one day and return the favor! Take care. – TweetyBug0 Sep 21 '21 at 20:33

2 Answers2

0

When you nest your loops, that means you want to run the inner loop over and over, every time the outer loop happens. That's clearly not what you actually mean to do here; your code is instead intended to iterate over the variables in lockstep, pairing up each username, fullname and UID. That means you should have only one loop instead of nesting multiple loops inside each other.

offset=0
while IFS= read -r username <&3 && IFS= read -r fullname <&4 && (( ++offset )); do
  useradd "$username" -m -c "$fullname" -u "$((100100 + offset))"
done 3<username.txt 4<fullnamecomment.txt
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thank you so much for taking the time to respond. Your response worked perfectly without any modifications and marked this as the answer. – TweetyBug0 Sep 21 '21 at 20:25
0

Resolution from SteveKline modified:

#!/bin/bash
Z=100101
IMPORTCSV=$(cat tabdelimituserlist.csv)
while read -r line; do
        U=$(echo $line | cut -f1 -d:)
        I=$(echo $line | cut -f2 -d:)

        echo "useradd "$U" -m -c "$I" -u "$Z""
        #useradd "$U" -m -c "$I" -u "$Z"

        #Optional since RHEL passwd permits stdin arguments
        #echo 73mp@ssw0rd | passwd --stdin "$U"

        Z=$(( $Z + 1 )) #Will increment 1 after 100100 for each user added
done <<< "$IMPORTCSV"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 1
    Don't use `echo $line | cut ...` to split fields, `read` can do that fine itself with e.g. `IFS=: read -r U I ignored`. See [BashFAQ #1: How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?](https://mywiki.wooledge.org/BashFAQ/001) Also, your quoting is rather messed up; [shellcheck.net](https://www.shellcheck.net) is good at pointing out quoting problems. – Gordon Davisson Sep 21 '21 at 20:46