我正在编写一个脚本,用于从 .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
您需要关注以下三件事:
- 用于迭代名称列表的循环结构
- 确定是否应删除用户的方法
- 用户删除
在伪代码中,该算法将类似于以下内容。
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 作为其输入。