2

I want to create a new user script that I can loop for creating a second or third.

So far I have something like this, but i'm stuck on the rest.

#!/bin/bash
echo "Do you want to create a new user (y/n): "
read createNewUser

while [[ createNewUser ]]; do
   echo "Enter username: "
   read username
   echo "Enter first name: "
   read firstname
   echo "Enter last name: "
   read lastname

   useradd -g staff -c "${firstname} ${lastname}" -s /bin/bash $username

   mkhomedir_helper $username

 done 

Do I ask the question again before the done statement or can I include it at the top of the loop instead?

2

Sounds like you're asking for the "Do you want to create a new user (y/n): " prompt and the input to be within the while conditional .

Try:

#!/bin/bash

while [[ "$(read -p "Do you want to create a new user (y/n): " x; echo $x)" == "y" ]] ; do
   echo "Enter username: "
   read username
   echo "Enter first name: "
   read firstname
   echo "Enter last name: "
   read lastname

   useradd -g staff -c "${firstname} ${lastname}" -s /bin/bash $username

   mkhomedir_helper $username
done

This should ask you for confirmation before an iteration begins.

2
  1. First of all, when your current script says while [[ createNewUser ]], it is essentially saying “while the constant string createNewUser is not an empty string”.  So your current script runs forever, even if you answer the question with no.  Since createNewUser is a variable, you need to reference it as $createNewUser.
  2. As you speculated and Jedi confirmed, if you want your script to create a user and then ask whether you want to do another, you need it to ask you as part of the loop.  Here’s another way of doing that; I believe (IMHO) that this is a bit more straightforward than Jedi’s answer:

    #!/bin/bash
    
    while read -p "Do you want to create a new user (y/n): " createNewUser  &&
          [[ "$createNewUser" == y* ]]
    do
        echo "Enter username: "
        read username
        echo "Enter first name: "
        read firstname
        echo "Enter last name: "
        read lastname
    
        useradd -g staff -c "$firstname $lastname" -s /bin/bash "$username"
    
        mkhomedir_helper "$username"
    done

    From the POSIX Shell Command Language Specification, the format of the while loop is as follows:

    while compound-list-1
    do
        compound-list-2
    done

    i.e., you can have multiple statements between the while and the do.  (I guess Jedi is bending over backwards to do it with a single command.)  My approach splits the query and the test into two separate simple statements.  The loop will continue to run as long as the read succeeds and the user response (i.e., your response) begins with y (because the two statements are separated by &&).

  3. As long as you’re using bash, and you’re using [[]] (instead of []), and you’re using == (instead of =), the right side of the test can be a pattern, like the ones you use for pathname expansion (i.e., globs/wildcards).  By testing [[ "$createNewUser" == y* ]], your script will accept any input beginning with y, such as yes, yeah, yup and you bet!

    Note that the y* must not be quoted, or else the script will accept only the literal string y*.

  4. You should always quote your shell variable references (e.g., "$username") unless you have a good reason not to, and you’re sure you know what you’re doing.  Strictly speaking, you might not need to in the [[ "$createNewUser" == y* ]] test (the first position in a [[ test in bash is treated specially), but it’s generally recommended that you get into the habit of always doing it unless you have a real reason not to.
  5. We quote variables to handle values that contain spaces and other special characters.  Your script would be better if you verified that $username contains only characters that are valid in usernames; otherwise, the useradd might fail.  (You might also want to check whether useradd fails by doing something like

        useradd -g staff -c "$firstname $lastname" -s /bin/bash "$username"  &&
        mkhomedir_helper "$username"

    or

        if useradd -g staff -c "$firstname $lastname" -s /bin/bash "$username"
        then
            mkhomedir_helper "$username"
        else
            echo "useradd failed"
        fi

    By extension, you might also want to test whether mkhomedir_helper succeeds or fails.)

  6. You don’t need { and } in "${firstname} ${lastname}".  See Using single or double bracket in bash for a discussion of [[]] vs. [] and when you need to use ${variable_name}.
  7. You might want to test whether firstname or lastname is null.  For example, if you were creating an account for the musician Sting, and you entered Sting as his first name and nothing as his last name, his name would be saved as Sting   (with a space at the end).  Consider something like

        if [ "$firstname" = "" ]
        then
            fullname="$lastname"
        elif [ "$lastname" = ""]
        then
            fullname="$firstname"
        else
            fullname="$firstname $lastname"
        fi
        useradd -g staff -c "$fullname" -s /bin/bash "$username"

    Or you could just ask a single question for the user’s full name.

  8. You might want to consider switching all your read statements to the read -p variety.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.