I'm working on a script to delete users from a .txt file but give the option to delete as a final failsafe.

The text file is called badUsers.txt

I'm basically modifying this script which I know works:

cat badUsers.txt | while read user
    echo "Deleting: ${user}"
    echo userdel -r "${user}"
done

This is the new version:

while true; do
    read -p "Should ${user} be deleted from the system? : " yn
    case $yn in
            [Yy]* ) echo "Deleting: ${user}"
                    echo userdel -r "${user}"
    break;;
    [Nn]* ) echo "next user"
        break;;
    * ) echo "Please answer yes or no.";;
    esac
    done

Everytime I run it, I keep getting an infinite loop but I'm not sure why. What am I doing wrong here?

There are 3 things you need to concern yourself with:

  1. The looping construct for iterating over the list of names
  2. The method for determining whether a user should be deleted
  3. The user deletion

In pseudo-code, the algorithm would be something like the following.

for each name N in the input file
    ask if N should be interpreted as a user and deleted; wait for a reply R
        if R is yes delete the user else skip

With respect to (3), we can reuse your approach. I have corrected to remove the echo as that prevents the user deletion.

With respect to (2), there are at least 2 ways.

read -p "Should ${user} be deleted? (yN)" -r yn
case $yn in
    ...
esac

and

echo Should ${user} be deleted?
select yn in "Y" "N"
do
    case $yn in
        ...
    done   
done

With respect to (1), there are at least 2 methods.

for user in $(<badUsers.txt)
do
    ...
done

while read -r user
do
    ...
done < badUsers.txt

The last method is similar to the cat construct you use above, but is preferred as it allows for file descriptor redirection. If we prefer the methods used in the example you provide, we get something like the following.

while read -u 3 -r user
do
    read -p "Should ${user} be deleted from the system? (yN)" -r yn
    case $yn in
        [Yy]) echo "Deleting: ${user}"
               userdel -r -- "${user}" 2> /dev/null
               ;;
        *) echo next user
           ;;
    esac
done 3< badUsers.txt

exit 0

As you may already know, read redirects the file to standard in, which is numbered 0. The nested read, used to prompt the user, inherits this redirected file descriptor. This means the read with the prompt will take its input from 0, which is now not the terminal, but a file.

To avoid this problem it is better redirect the file to descriptor 3, and configure the outer read to use descriptor 3 as its input.

  • Thanks for your comment! I tried running it the third way you showed and I get an error: ./automatic_user_management.sh: 32: read: Illegal option -u – Daniel Nov 12 at 19:48

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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