脚本跳过嵌套 case 语句中的用户输入

脚本跳过嵌套 case 语句中的用户输入

我正在尝试创建一个嵌套的 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”是要显示的内容,而不是用于存储答案的变量。

相关内容