script ignorando a entrada do usuário na instrução de caso aninhado

1

Estou tentando criar uma instrução de caso aninhada na qual a entrada do usuário é esperada (S / N). No entanto, o sistema nunca espera pela entrada e vai sempre para a terceira opção, "Por favor, responda sim ou não". Alguém pode me dizer o que eu estou sentindo falta?

Aqui está a declaração do caso

#!/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

Funcionando sob o Ubuntu 14.04 LTS

Exemplo de saída

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.
    
por Ubuntuser 26.06.2014 / 09:03

3 respostas

3

Você está canalizando find output para o loop while. O comando interno de leitura está lendo uma linha da saída de find , não de stdin.

Você pode reestruturar assim: envia a saída find para o loop while em um descritor de arquivo diferente. Isso deixa o stdin livre para a leitura interna.

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)

Isso usa uma substituição de processo , em vez de um canal, para ler de find

    
por glenn jackman 26.06.2014 / 15:00
2

O contexto desta vez fornece a resposta. Você está distribuindo a saída de find em todo o loop while, e isso inclui a sua leitura interna também ... o que significa que o seu "read yn" também lerá da mesma saída que "find" fornece, ao contrário do seu teclado.

Eu também não gosto de sua manipulação geral de looping em arquivos. Um simples:

for file in /etc/init.d/*; do
   echo Processing $file
done

geralmente funciona bem hoje em dia, mesmo para grandes quantidades de arquivos.

Se você realmente precisa usar o find, talvez você possa incluir seu manipulador em outro script e chamá-lo para cada arquivo com:

find /etc/init.d -type f -perm +111 -exec myhandlerscript.sh {} \;

Isso localizará todos os arquivos com permissões executáveis e chamará myhandlerscript.sh para cada um com o nome como argumento. Dentro do script, o nome do arquivo aparecerá dentro da variável especial $ 1.

Se realmente deve estar no mesmo arquivo, coloque o código dentro de uma função, exporte-o com "export -f myfunction" e use "-exec bash -c 'myfunction" $ 0 "' {} \;" como um parâmetro para encontrar.

    
por Whyte 26.06.2014 / 14:44
1

Seu uso do comando "read" não parece estar certo.

read -p "Do you wish to input data ?" yn

O comutador -p espera uma cadeia de caracteres próxima a ela, que será usada como o Prompt. Assim, pensava que "yn" era algo para exibir, em vez da variável para armazenar a resposta.

    
por Whyte 26.06.2014 / 09:42