Solicita ao usuário um tipo de arquivo em um loop while

Solicita ao usuário um tipo de arquivo em um loop while

Estou ajustando um script para que ele solicite ao usuário um arquivo de um tipo específico. Se o arquivo inserido não corresponder ao tipo de arquivo específico, ele entra em um loop while e se repete até que o usuário insira o arquivo correto.

Nesse caso, estou solicitando ao usuário um .ziparquivo em:

read -p "Enter zip file: " package1
 while [ package1 != *.zip ] ; do
     read -p "Please enter file ending in '.zip': " package1
 done <<< package1
echo $package1

Eu tive erros até este ponto. Agora, recebo apenas um cursor em branco, sem saída. Quer eu entre *.zipou não, ele avança para a próxima linha com um cursor em branco e sem saída.

Pensamentos?

EDITAR:

Tudo bem, decidi usar o selectloop e é uma opção muito melhor do que whileneste caso.

Mas e se esse ziparquivo (ou qualquer tipo de arquivo solicitado) pudesse estar em qualquer outro diretório? Quero dar a opção de alterar diretórios enquanto estiver no select-loopshell.

Eu tentei até agora:

echo Select zip file:
                options=(".." *.zip)
                select package1 in "${options[@]}" ; do
                        case $package1 in
                                1 ) cd ..; echo Select zip file: ;;
                                # Different Directory ) ;;
                                * ) break ;;
                        esac
                done

Mas o loop não exibirá novamente os itens de menu após alterar os diretórios. Não tenho certeza de como oferecer ao usuário cdum caminho totalmente diferente do que ../ele deseja, nem para que usar

"All other existing \# file items" ) ... ; break;;

dentro decase

Responder1

Torne isso logicamente mais fácil examinando apenas a extensão final:

while [ "${package1##*.}" != "zip" ]
do
    read -e -p "Specify a .zip file: " package1
done
echo $package1

Responder2

Uma solução mais elegante foi postada, mas acho importante apontar alguns dos erros que estão causando a falha do seu script original e como corrigi-los.

Primeiro, ao testar a variável package1em seu loop while, você precisa colocar o $na frente dela para ler os dados reais armazenados nessa variável.

Em seguida, use [[...]]em vez de [...]no teste de loop while, pois isso permite que você faça a correspondência de padrões usando seu curinga *. No entanto, isso só funciona no bash e não no sh. Por favor, vejaesseresponda para obter uma explicação completa sobre o uso de [[...]]versus [...].

Por último, você não precisa passar a string <<< package1no final do loop while.

Aqui está uma versão modificada do seu script que funciona conforme o esperado.

#!/bin/bash

read -p "Enter zip file: " package1
while [[ "$package1" != *.zip ]]; do
    read -p "Please enter file ending in '.zip': " package1
    done 
echo $package1

Responder3

Nunca faça com que o usuário digite nomes de caminhos de arquivos de forma interativa. É mais fácil para eles chamar seu script com os nomes dos caminhos de seus arquivos Zip na linha de comando do script. Isso permite que eles usem o recurso de conclusão de nome de arquivo e os padrões de globbing de nome de arquivo do shell.

O script seria chamado usando, por exemplo

./myscript /some/path/myarchive.zip

ou

./myscript folder/archive-*.zip

ou similar.

No roteiro, você faria

#!/bin/bash

for archive_path do
    printf 'Processing archive "%s"...\n' "$archive_path"

   # code to process "$archive_path" goes here
done

O loop no script percorreria todos os argumentos passados ​​para o script e, em cada iteração, "$archive_path"seria o nome do caminho de um arquivo individual passado para o script.

Não há necessidade de verificar se o nome do "$archive_path"arquivo termina com alguma string específica, pois as ferramentas que você usaria no arquivo podem nem se importar com o sufixo do nome do arquivo. Se o fizerem, eles falharão com o código de saída apropriado, que você pode capturar facilmente:

if ! unzip "$archive_path"; then
    printf 'Failed to run unzip on "%s"\n' "$archive_path" >&2
    exit 1
fi

Se você usar set -eno script (provavelmente como sua primeira instrução), ele sairá automaticamente quando qualquer comando (que não faz parte de uma instrução condicional) retornar com um código de saída diferente de zero.

set -e

# The following would terminate the script if it failed:
unzip "$archive_path"

Em relação à sua "edição" adicionada: O que você está fazendo é começar a implementar uma ferramenta de navegador de arquivos ou gerenciador de arquivos para selecionar arquivos Zip. Dependendo da finalidade para a qual você realmente deseja usar esse código, isso pode ser um exagero.

Responder4

Se você quiser que o usuário selecione um deexistirarquivos, eu usaria selectem vez de read, para permitir que o usuário selecione em uma lista, em vez de escrever um nome de arquivo que ele talvez não saiba exatamente.

select package1 in *.zip; do
    break;
done
echo "$package1"

O usuário verá uma lista e digitará o número.

informação relacionada