Conditions Bash: comment «et» les expressions? (si [! -z $ VAR && -e $ VAR])


281

Je suppose que je ne sais pas trop comment faire "et" les tests. Je voulais m'assurer qu'il existait un argument qui fonctionnait bien [ -e $VAR ], mais il s'avère qu'il était également évalué comme vrai sur une chaîne vide; ce que je ne veux pas.

Comment puis-je les «et» ensemble? Ou existe-t-il un autre test unaire qui accomplit ce que je veux?

Réponses:


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

9
Cette solution fonctionne même dans des shells strictement POSIX et donc également dans bash; cependant, pour profiter pleinement des «bashismes», voir la réponse de @ paxdiablo.
mklement0

2
Très heureux de voir cela conseillé au lieu de l'obsolescence -a.
Charles Duffy

1
J'en ai trouvé une autre excellente et détaillée - stackoverflow.com/questions/3601515/…
valentt

70

Depuis la bashpage de manuel:

[[ expression ]] - retourner un état de 0 ou 1 selon l'évaluation de l'expression d'expression conditionnelle.

Et, pour les expressions, l'une des options est:

expression1 && expression2- vrai si les deux expression1et expression2sont vrais.

Vous pouvez donc andles regrouper comme suit ( -nc'est l'opposé de -zce que nous pouvons éliminer !):

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

Cependant, je ne pense pas que ce soit nécessaire dans ce cas, -e xyzzyc'est vrai si le xyzzy fichier existe et peut assez facilement gérer des chaînes vides. Si c'est ce que vous voulez, vous n'avez pas réellement besoin de la -zvérification non vide:

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

En d'autres termes, utilisez simplement:

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

1
Nous pouvons le raccourcir avec[[ -e "$var" ]] && echo "'$var' exists"
Jaypal Singh

1
Oui, s'il s'agit d'un monoplace (comme mon exemple). Je ne ferais pas cela si le bloc conditionnel était beaucoup plus complexe.
paxdiablo

dans le cas où il n'y a qu'une seule commande - peut-être même longue -, il est logique d'utiliser ce formulaire car il est plus court
avp

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

 


10
Puisque POSIXne définit pas le comportement de [avec des ensembles de tests complexes, nous devons éviter d'utiliser -aou -oavec [. Je l'ai lu ici .
jaypal singh

2
@ jaypal-singh Vous avez raison, mais le sujet a une bashbalise et ne mentionne pas POSIX, donc je poste cette version qui fonctionne sous bashet quelques autres shells modernes.
Slava Semushin

2
Si vous supposez l'utilisation de bashou d'autres coquilles modernes, il y a encore moins de raisons de recommander -a.
chepner

Même avec bash, le comportement de ces tests n'est pas bien défini dans tous les cas d'angle. Considérez [ "$var1" -o "$var2" ]; si var1=(et var2=), alors ce que nous avons est un test pour savoir s'il -oest non vide, plutôt que si l'un var1ou l'autre var2n'est pas vide. Ce genre d'ambiguïté est la seule raison légitime de l' x$varidiome dans les commandes modernes (c'est-à-dire postérieures aux années 90) testavec des citations correctes, et cet idiome doit mourir dans un incendie.
Charles Duffy

4

Citez simplement votre variable:

[ -e "$VAR" ]

Cela évalue [ -e "" ]si$VAR est vide.

Votre version ne fonctionne pas car elle est évaluée [ -e ]. Dans ce cas, bash vérifie simplement si le seul argument (-e ) est une chaîne non vide.

Depuis la page de manuel:

tester et [évaluer les expressions conditionnelles à l'aide d'un ensemble de règles basées sur le nombre d'arguments. ...

1 argument

L'expression est vraie si et seulement si l'argument n'est pas nul.

(De plus, cette solution a l'avantage supplémentaire de travailler avec des noms de fichiers contenant des espaces)


1

J'ai trouvé une réponse maintenant. Merci pour vos suggestions!

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

Des commentaires à ce sujet? Il semble inefficace de grep deux fois, mais ça marche ...

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.