Multi declaração se condição no bash

0

Eu queria executar várias instruções em uma condição if da seguinte forma:

[[ -e cli.tar.gz ]] && 'tar -xvf cli.tar.gz -C ~/' || 
        echo "cli.tar.gz can not be found. Exiting" >&2 && exit 1

O que aconteceu é que a saída 1 foi atingida quando cli.tar.gz é encontrado e alcatroado, ou seja, exatamente o oposto do que eu estava tentando alcançar, então adicionei parênteses ao redor da parte depois da OR como segue

[[ -e cli.tar.gz ]] && tar -xvf cli.tar.gz -C ~/ || 
   { echo "cli.tar.gz can not be found. Exiting" >&2; exit 1; }

Recebi um erro token inesperado '}' no final da função (esta linha faz parte de uma função)

Eu resolvi meu problema escrevendo uma boa condição formatada se

if [[ -e cli.tar.gz ]]
then
    if [[ ! 'tar -xvf cli.tar.gz -C ${UDM_REMOTE}' ]]
    then
        echo "cli.tar.gz can not be found. Exiting" >&2; exit 1;
    fi
fi

Mas ainda assim, qual teria sido a solução de fazer uma condição aninhada em uma linha como o que eu tentei alcançar inicialmente?

Atualização 1 Graças às respostas de @uwe e @goldilocks atualizei a declaração da seguinte forma que agora funciona

[[ ! -e cli.tar.gz ]] && ! 'tar -xvf cli.tar.gz -C ~/' && \ 
  echo "cli.tar.gz can not be found (or tar failed). Exiting" >&2 && exit 1
    
por Moataz Elmasry 13.11.2013 / 10:57

3 respostas

4

if [[ ! -e cli.tar.gz ]] || ! tar -xvf cli.tar.gz -C ~/ ; then 
    echo "cli.tar.gz can not be found (or tar failed). Exiting" >&2 && exit 1
fi

ou, se você quiser evitar o if completamente:

( [[ ! -e cli.tar.gz ]] || ! tar -xvf cli.tar.gz -C ~/ ) && { echo "cli.tar.gz can not be found (or tar failed). Exiting" >&2 ; exit 1 ; }
    
por 13.11.2013 / 11:56
4
if [[ -e cli.tar.gz && ( $(tar -xvf cli.tar.gz -C ~/) && $? != 0 ) ]]; then 
    echo "cli.tar.gz can not be found (or tar failed). Exiting" >&2 && exit 1
fi
    
por 13.11.2013 / 11:15
2

A maneira como você está usando && e || é uma lista, não uma condicional.

Lists
   A list is a sequence of one or more pipelines separated by one of the 
   operators ;, &, &&, or ⎪⎪, and optionally terminated by one of ;, &, or 
   <newline>.

   Of these list operators, && and ⎪⎪ have equal precedence, followed by ; 
   and &, which have equal precedence.

   A sequence of one or more newlines may appear in a list instead of a 
   semicolon to delimit commands.

   If a command is terminated by the control operator &, the shell executes 
   the command in the background in a subshell.  The shell does not wait for 
   the command  to  finish,  and the  return  status  is 0.  Commands 
   separated by a ; are executed sequentially; the shell waits for each 
   command to terminate in turn.  The return status is the exit status of
   the last command executed.

   AND and OR lists are sequences of one of more pipelines separated by the 
   && and ⎪⎪ control operators, respectively.  AND and OR lists are executed 
   with left associativity.   An AND list has the form

          command1 && command2

   command2 is executed if, and only if, command1 returns an exit status of 
   zero.

   An OR list has the form

          command1 ⎪⎪ command2

   command2 is executed if and only if command1 returns a non-zero exit 
   status.  The return status of AND and OR lists is the exit status of the 
   last command executed in the list.

Se você der uma olhada neste SO Q & A intitulado: Operadores lógicos simples no BASH , @Gilles answer é tão conciso quanto possível em termos de explicar como lidar com if / then blocks no Bash.

Corrida re-fatorada # 1

Portanto, uma versão reformulada da sua declaração if/then :

[[ -e cli.tar.gz && 'tar -xvf cli.tar.gz -C ~/' || 
        echo "cli.tar.gz can not be found. Exiting" >&2 && exit 1

ficaria assim:

if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1; fi

Ou expandido para legibilidade:

if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then 
  echo "cli.tar.gz can not be found. Exiting" >&2
  exit 1
fi

Exemplo de execução

Dados da amostra. Conteúdo do tarball:

$ tar ztvf cli.tar.gz 
drwxrwxr-x saml/saml         0 2013-11-13 08:26 1/
drwxrwxr-x saml/saml         0 2013-11-13 08:26 1/2/
drwxrwxr-x saml/saml         0 2013-11-13 08:26 1/2/3/
drwxrwxr-x saml/saml         0 2013-11-13 08:26 1/2/3/4/

Informações do arquivo:

$ ls -l cli.tar.gz 
-rw-rw-r-- 1 saml saml 146 Nov 13 08:27 cli.tar.gz

$ ls out/
1

Executando nosso comando:

$ if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1; fi

Nada aconteceu. Se nós removermos o diretório de saída. out :

$ mv out out_ORIG

E execute novamente:

$ if [[ -e cli.tar.gz && ! $(tar xvf cli.tar.gz -C out) ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; fi
tar: out: Cannot chdir: No such file or directory
tar: Error is not recoverable: exiting now
cli.tar.gz can not be found. Exiting

O que aconteceu? Por um lado você geralmente não quer misturar a execução de comandos em um if / then como você está tentando fazer. Há muitos problemas que podem dar errado.

Corrida re-fatorada # 2

Em vez disso, eu estruturaria meu código dessa forma, já que isso nos dá o caminho mais fácil para lidar com os problemas à medida que eles surgem, em vez de tentar construir algum código ridículo que até você, o autor, terá dificuldades em entender. você estava fazendo!

if [[ -e cli.tar.gz ]]; then 
  cmdOutput=$(tar xvf cli.tar.gz -C out 2>&1); 
  if [[ $? != 0 ]]; then 
    echo "cli.tar.gz can not be found. Exiting" >&2
    exit 1
  fi
fi

Exemplo

$ ls -l |grep -E "cli|out"
-rw-rw-r-- 1 saml saml  146 Nov 13 08:27 cli.tar.gz
drwxrwxr-x 3 saml saml 4096 Nov 13 09:28 out

Agora execute nosso comando (nada acontece):

$ if [[ -e cli.tar.gz ]]; then cmdOutput=$(tar xvf cli.tar.gz -C out 2>&1); if [[ $? != 0 ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1;fi;fi
$ 

Agora execute nosso comando (sem dir. out present):

$ rm -fr out
$ ls -l |grep -E "cli|out"
-rw-rw-r-- 1 saml saml  146 Nov 13 08:27 cli.tar.gz

$ if [[ -e cli.tar.gz ]]; then cmdOutput=$(tar xvf cli.tar.gz -C out 2>&1); if [[ $? != 0 ]]; then echo "cli.tar.gz can not be found. Exiting" >&2; exit 1;fi;fi
cli.tar.gz can not be found. Exiting
    
por 13.11.2013 / 15:32

Tags