There are 3 things you need to concern yourself with:
- The looping construct for iterating over the list of names
- The method for determining whether a user should be deleted
- 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.