从列表中删除用户

从列表中删除用户

我正在编写一个脚本,用于从 .txt 文件中删除用户,但提供删除选项作为最终的故障保护。

该文本文件名为 badUsers.txt

我基本上正在修改这个我知道有效的脚本:

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

这是新版本:

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

每次运行它,我都会陷入无限循环,但我不知道为什么。我在这里做错了什么?

答案1

您需要关注以下三件事:

  1. 用于迭代名称列表的循环结构
  2. 确定是否应删除用户的方法
  3. 用户删除

在伪代码中,该算法将类似于以下内容。

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

关于 (3),我们可以重复使用您的方法。我已更正为删除回声,因为这会阻止用户删除。

对于(2),至少有两种方法。

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

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

对于(1),至少有两种方法。

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

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

最后一种方法类似于上面使用的 cat 构造,但最好使用,因为它允许文件描述符重定向。如果我们更喜欢您提供的示例中使用的方法,我们会得到类似下面的结果。

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

您可能已经知道,read 将文件重定向到标准输入,其编号为 0。用于提示用户的嵌套 read 继承了这个重定向的文件描述符。这意味着带有提示的 read 将从 0 获取输入,现在它不再是终端,而是一个文件。

为了避免这个问题,最好将文件重定向到描述符 3,并将外部读取配置为使用描述符 3 作为其输入。

相关内容