Les deux -a
et -e
options dans documentation Bash est dit:
-a file
True if file exists.
-e file
True if file exists.
En essayant de comprendre la différence, j'ai exécuté le script suivant:
resin_dir=/Test/Resin_wheleph/Results
if [ -e ${resin_dir} ] ; then
echo "-e ";
fi
if [ ! -e ${resin_dir} ] ; then
echo "! -e";
fi
if [ -a ${resin_dir} ] ; then
echo "-a";
fi
if [ ! -a ${resin_dir} ] ; then
echo "! -a";
fi
/Test/Resin_wheleph/Results
existe et est un répertoire. Et voici ce que j'obtiens:
-e
-a
! -a
ce qui semble un peu étrange (remarquez -a
et ! -a
). Mais quand j'utilise des crochets doubles (par exemple, _ if [[ -e ${resin_dir} ]]
) dans le script similaire, il donne une sortie raisonnable:
-e
-a
Donc:
-a
et -e
options?-a
produit un résultat étrange lorsqu'il est utilisé à l'intérieur de crochets simples?J'ai fait des recherches, et c'est assez poilu:
-a
est obsolète, il n'est donc pas répertorié dans la page de manuel de /usr/bin/test
plus, mais toujours dans celui de bash. Utilisation -e
. Pour le '[' simple, le module intégré bash se comporte de la même façon que le module intégré test
bash, qui se comporte de la même manière que /usr/bin/[
et /usr/bin/test
(l'un est un lien symbolique vers l'autre). Notez l'effet de -a
dépend de sa position: s'il est au début, cela signifie file exists
. Si c'est au milieu de deux expressions, cela signifie logique and
.
[ ! -a /path ] && echo exists
ne fonctionne pas, car le manuel bash souligne que -a
est considéré comme un opérateur binaire, et donc ce qui précède n'est pas analysé en tant que negate -a ..
mais en tant que if '!' and '/path' is true
(non vide). Ainsi, votre script génère toujours "-a"
(qui teste les fichiers) et "! -a"
qui est en fait un binaire and
ici.
Pour [[
, -a
n'est plus utilisé comme binaire and
(&&
y est utilisé), son but unique est donc de rechercher un fichier là-bas (bien qu'il soit obsolète). La négation fait donc ce que vous attendez.
L'option '-a
' De l'opérateur de test a une signification en tant qu'opérateur unaire et une autre en tant qu'opérateur binaire. En tant qu'opérateur binaire, c'est le connectif 'et' (et '-o
' Est le 'ou' connectif). En tant qu'opérateur unaire, il teste apparemment l'existence d'un fichier.
Le système autoconf
vous conseille d'éviter d'utiliser '-a
' Car cela crée de la confusion; maintenant je vois pourquoi. En effet, dans la programmation Shell portable, il est préférable de combiner les conditions avec '&&
' Ou '||
'.
Je pense que @litb est sur la bonne voie. Lorsque vous avez '! -a ${resin_dir}
', Bash peut l'interpréter comme "est la chaîne '!' non vide et est la chaîne dans '$ {resin_dir}' non vide, à laquelle la réponse est oui. Le Korn Shell a une vue différente à ce sujet, et le Bourne Shell encore une autre vue - alors restez à l'écart de '-a
'.
Sous Solaris 10:
$ bash -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi'
Bad
$ ksh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi'
OK
$ sh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi'
sh: test: argument expected
$
Le double crochet [[exp]] est une commande bash intégrée. En bash, -a et -e sont les mêmes, probablement pour une certaine compatibilité descendante.
Le crochet simple [exp] est un alias pour la commande externe "test". Dans "test", -a est un ET logique. Bien que [rien AND $ STRING] semble être faux, test a quelques bizarreries syntaxiques, c'est pourquoi je recommande d'utiliser le bash intégré [[exp]], qui a tendance à être plus sain d'esprit.
Remarque: bash appelle vraiment/bin/[lorsque vous utilisez "[".
$ [ $UNASIGNED_VAR == "bar" ]
bash: [: ==: unary operator expected
l'erreur montre bash appelé [. Une strace affiche également "execve ("/usr/bin/[", ..."