Condicionais Bash: como “e” expressões? (se [! -z $ VAR && -e $ VAR])


281

Acho que não sou claro sobre como fazer "e" testes. Eu queria ter certeza de que existia um argumento que funcionasse bem [ -e $VAR ], mas acontece que também estava sendo avaliado como verdadeiro em uma string vazia; o que eu não quero.

Como eu os 'e' juntos? Ou há outro teste unário que realiza o que eu quero?

Respostas:


532
if [ ! -z "$var" ] && [ -e "$var" ]; then
      # something ...
fi

9
Esta solução funciona mesmo em invólucros estritamente compatíveis com POSIX e, portanto, também em bash; no entanto, para aproveitar ao máximo os "basismos", consulte a resposta de @ paxdiablo.
precisa saber é o seguinte

2
Muito feliz em ver isso avisado em vez de obsoleto -a.
Charles Duffy

1
Eu encontrei outra explicação excelente e detalhada - stackoverflow.com/questions/3601515/… #
11287 valentt

70

Na página de bashmanual:

[[ expression ]] - retorna um status de 0 ou 1, dependendo da avaliação da expressão da expressão condicional.

E, para expressões, uma das opções é:

expression1 && expression2- verdadeiro se ambos expression1e expression2são verdadeiros.

Para que você possa andreuni-los da seguinte forma ( -né o oposto de -zpara nos livrarmos do !):

if [[ -n "$var" && -e "$var" ]] ; then
    echo "'$var' is non-empty and the file exists"
fi

No entanto, acho que não é necessário, neste caso, -e xyzzyé verdade se o xyzzy arquivo existe e pode lidar facilmente com cadeias de caracteres vazias. Se é isso que você deseja, na verdade você não precisa da verificação -znão vazia:

pax> VAR=xyzzy
pax> if [[ -e $VAR ]] ; then echo yes ; fi
pax> VAR=/tmp
pax> if [[ -e $VAR ]] ; then echo yes ; fi
yes

Em outras palavras, basta usar:

if [[ -e "$var" ]] ; then
    echo "'$var' exists"
fi

1
Podemos encurtá-lo com[[ -e "$var" ]] && echo "'$var' exists"
jaypal singh

1
Sim, se for uma linha (como meu exemplo foi). Eu não faria isso se o bloco condicional fosse muito mais complexo.
22412

no caso de haver apenas um - talvez até mesmo longa - comando, faz sentido utilizar este formulário, pois é mais curto
avp

9
if [ -n "$var" -a -e "$var" ]; then
    do something ...
fi

 


10
Como POSIXnão define o comportamento de [conjuntos complexos de testes, devemos evitar usar -aou -ocom [. Eu li aqui .
Jaypal singh

2
@ jaypal-singh Você está certo, mas o tópico tem uma bashtag e não menciona o POSIX, então eu posto esta versão que funciona sob bashoutras conchas modernas.
Slava Semushin

2
Se você está assumindo o uso de bashou outras conchas modernas, há ainda menos motivos para recomendar -a.
chepner

Mesmo com o bash, a maneira como esses testes se comportam não é bem definida em todos os casos de canto. Considere [ "$var1" -o "$var2" ]; if var1=(e var2=), então o que temos é um teste para saber se -oestá vazio, e não se está vazio var1ou var2não. Esse tipo de ambiguidade é a única razão legítima para o x$varidioma nos testcomandos modernos (isto é, pós-anos 90) com citações corretas, e esse idioma precisa morrer em um incêndio.
Charles Duffy

4

Simplesmente cite sua variável:

[ -e "$VAR" ]

Isso avalia [ -e "" ]se$VAR está vazio.

Sua versão não funciona porque é avaliada como [ -e ]. Agora, neste caso, o bash simplesmente verifica se o argumento único (-e ) é uma sequência não vazia.

Na página de manual:

testar e [avaliar expressões condicionais usando um conjunto de regras com base no número de argumentos. ...

1 argumento

A expressão é verdadeira se e somente se o argumento não for nulo.

(Além disso, esta solução tem o benefício adicional de trabalhar com nomes de arquivos contendo espaços)


1

Encontrei uma resposta agora. Obrigado por suas sugestões!

for e in ./*.cutoff.txt; do
if grep -q -E 'COX1|Cu-oxidase' $e
then
    echo xyz >$e.match.txt
else
    echo
fi

if grep -q -E 'AMO' $e
then
    echo abc >$e.match.txt
else
    echo
fi; done

Algum comentário sobre isso? Parece ineficiente grep duas vezes, mas funciona ...

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.