我正在尝试创建一个嵌套的 case 语句,其中需要用户输入(Y/N)。但是,系统从不等待输入,总是转到第三个选项“请回答是或否”。有人能告诉我我遗漏了什么吗?
以下是案例陈述
#!/bin/bash
STATUS=status
find /etc/init.d/* -name '*' -print0 | while IFS= read -r -d '' FILE;
do
if [ "$FILE" != "." -o "$FILE" != ".." ]; then
OUTPUT=$($FILE $STATUS)
case "$OUTPUT" in
*disabled* )
echo "Do you wish to start $FILE ?"
read yn
case $yn in
[yY] | [yY][Ee][Ss] )
$FILE start
;;
[nN] | [n|N][O|o] )
;;
* )
echo "Please answer yes or no.";;
esac
;;
* )
echo "App $FILE is running"
;;
esac
fi
done
在 Ubuntu 14.04 LTS 下运行
示例输出
App /etc/init.d/reboot is running
App /etc/init.d/resolvconf is running
App /etc/init.d/rsync is running
App /etc/init.d/rsyslog is running
App /etc/init.d/samba is running
App /etc/init.d/samba-ad-dc is running
Do you wish to start /etc/init.d/saned ?
Please answer yes or no.
答案1
您正在将输出传输到 while 循环。内部 read 命令正在从的输出(而不是从 stdin)find
读取一行。find
您可以像这样重构:将find
输出发送到不同文件描述符上的 while 循环。这样可以让 stdin 自由地用于内部读取。
while IFS= read -u3 -r -d '' FILE; do
if [ "$FILE" != "." -o "$FILE" != ".." ]; then
OUTPUT=$($FILE $STATUS)
case "$OUTPUT" in
*disabled* )
read -p "Do you wish to start $FILE ?" yn
case $yn in
[yY] | [yY][Ee][Ss] ) $FILE start ;;
[nN] | [nN][Oo] ) ;;
* ) echo "Please answer yes or no.";;
esac
;;
* ) echo "App $FILE is running" ;;
esac
fi
done 3< <(find /etc/init.d/* -name '*' -print0)
这使用流程替代,而不是管道,读取find
答案2
这次的上下文提供了答案。您将 find 的输出导入到整个 while 循环中,这也包括您的内部读取...这意味着您的“read yn”也将从“find”提供的相同输出中读取,而不是从键盘读取。
我也不喜欢你对文件循环的一般处理方式。一个简单的:
for file in /etc/init.d/*; do
echo Processing $file
done
现在通常可以很好地工作,即使对于大量文件也是如此。
如果你确实必须使用 find,你也许可以将你的处理程序包装在另一个脚本中,并使用以下命令为每个文件调用它:
find /etc/init.d -type f -perm +111 -exec myhandlerscript.sh {} \;
这将查找所有具有可执行权限的文件,并以名称作为参数对每个文件调用 myhandlerscript.sh。在脚本内部,文件名将出现在 $1 特殊变量中。
如果确实必须在同一个文件中,则将代码包装在函数内部,使用“export -f myfunction”导出,并使用“-exec bash -c 'myfunction "$0"' {} \;”作为参数进行查找。
答案3
您对“读取”命令的使用似乎不太正确。
read -p "Do you wish to input data ?" yn
-p 开关要求紧挨着它的是一个字符串,它将被用作提示符。因此它认为“yn”是要显示的内容,而不是用于存储答案的变量。