Bash Script Teste de Argumento Vazio

2

Estou tentando escrever um script simples com a seguinte lógica: SE o primeiro argumento for um arquivo regular válido, execute o loop for; se nenhum argumento for fornecido, execute "code2"; tudo mais, execute "code3". O script a seguir parece OK para mim, mas ficou preso se for executado sem um argumento.

#!/bin/bash

if [ -f $1 ]; then
  for i in 'cat $1'
  do
    <something>
  done
elif [ $# -eq 0 ]; then
  "code2"
else
  "code3"
fi

Aqui está a saída de depuração e ficou presa no final.

bash -x myscript
+ '[' -f ']'
++ cat

Como não forneço argumentos, por que ele ainda é executado no primeiro fluxo if-then? Eu sou novo no bash scripting. Qualquer ajuda seria grata.

    
por cody 12.02.2018 / 02:38

2 respostas

2

Se você não citar a variável "$1" , ela se tornará nada e desaparecerá. O código executado é então (conforme relatado pela opção -x do shell):

[ -f ]

O qual, como -f é uma string com um comprimento diferente de zero, resulta em um teste verdadeiro e executa a parte then .

Você precisa escrever (pelo menos):

[ -f "$1" ]

Que, com um argumento vazio, se tornará

[ -f "" ]

e relatar uma falha para corresponder ao arquivo "" .

Uma outra alternativa é usar uma expansão de parâmetro (sem necessidade de cotação externa):

[ -f ${1:-""} ]

Ele será expandido para "" se o valor de $1 for nulo ou vazio.

E por favor, não faça um loop para percorrer as linhas de um arquivo. Você deve considerar usar um while read loop

#!/bin/sh

if [ -f ${1:-""} ]; then
  while read -r line; do
      echo '<something>'
  done <"$1"
elif [ "$#" -eq 0 ]; then
  echo "code2"
else
  echo "code3"
fi
    
por 12.02.2018 / 02:57
0

A resposta simples é porque com $1 inexistente, que também não é citado (também parte do problema), o shell trata a expressão como [ -f ] e o -f que [ vê aqui não é reconhecido como bandeira, mas apenas uma única "expressão". É na verdade o mesmo que:

$ [ abracadabra  ] && echo "success"
success

E para citar test manual (que, caso você não saiba, é alias para [ ):

   An  omitted  EXPRESSION  defaults  to false.  Otherwise, EXPRESSION is true or false and sets exit
   status.  It is one of:

   ( EXPRESSION )
          EXPRESSION is true

Observe que, se você citou a expressão, seria semelhante ao rastrear a saída, ou seja, tentaria avaliar uma string nula como nome de arquivo existente:

$ (set -x; [ -f "$this_var_doesnt_exist"  ] && echo "hi" )
+ '[' -f '' ']'
    
por 12.02.2018 / 02:54