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 .zip
arquivo 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 *.zip
ou 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 select
loop e é uma opção muito melhor do que while
neste caso.
Mas e se esse zip
arquivo (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-loop
shell.
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 cd
um 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 package1
em 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 <<< package1
no 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 -e
no 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 select
em 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.