262 votes

Signification de l'erreur "[ : too many arguments" de if [] (crochets)

Je n'ai pas pu trouver une seule ressource simple et directe expliquant la signification et la correction de l'erreur suivante de l'interpréteur de commandes BASH.

L'erreur :

-bash: [: too many arguments

Version adaptée à Google : bash open square bracket colon too many arguments .

Le contexte : une condition "si" entre crochets simples avec un opérateur de comparaison simple comme "égal", "supérieur à", etc :

VARIABLE=$(/some/command);
if [ $VARIABLE == 0 ]; then
  # some action
fi

1 votes

Où se trouve le code qui a produit cette erreur spécifique ?

0 votes

428voto

user568458 Points 3511

Si votre $VARIABLE est une chaîne de caractères contenant des espaces ou d'autres caractères spéciaux, et des crochets simples sont utilisés (qui est un raccourci pour le test ), alors la chaîne peut être divisée en plusieurs mots. Chacun de ces mots est traité comme un argument distinct.

Alors que une variable est divisée en plusieurs arguments :

VARIABLE=$(/some/command);  
# returns "hello world"

if [ $VARIABLE == 0 ]; then
  # fails as if you wrote:
  # if [ hello world == 0 ]
fi 

Il en sera de même pour tout appel de fonction qui dépose une chaîne de caractères contenant des espaces ou d'autres caractères spéciaux.


Correction facile

Enveloppez la sortie de la variable entre des guillemets doubles, pour qu'elle reste une seule chaîne (donc un seul argument). Par exemple,

VARIABLE=$(/some/command);
if [ "$VARIABLE" == 0 ]; then
  # some action
fi 

C'est aussi simple que cela. Mais passez à "Attention aussi..." ci-dessous si vous ne pouvez pas non plus garantir que votre variable ne sera pas une chaîne vide, ou une chaîne qui ne contient que des espaces.


Ou, un solution de rechange est d'utiliser des doubles crochets (ce qui est un raccourci pour l'option new test commande).

Cependant, ceci n'existe que dans bash (et apparemment korn et zsh), et peut donc ne pas être compatible avec les shells par défaut appelés par /bin/sh etc.

Cela signifie que sur certains systèmes, il peut fonctionner à partir de la console mais pas lorsqu'il est appelé ailleurs, par exemple à partir de cron selon la façon dont tout est configuré.

Cela ressemblerait à ceci :

VARIABLE=$(/some/command);
if [[ $VARIABLE == 0 ]]; then
  # some action
fi 

Si votre commande contient des doubles crochets comme ceci et que vous obtenez des erreurs dans les journaux mais qu'elle fonctionne à partir de la console, essayez d'intervertir les éléments suivants [[ pour une alternative suggérée ici, ou, assurez-vous que ce qui exécute votre script utilise un shell qui supporte [[ alias new test .


Méfiez-vous également de la [: unary operator expected erreur

Si vous voyez l'erreur "trop d'arguments", il y a de fortes chances que vous obteniez une chaîne de caractères d'une fonction dont la sortie est imprévisible. S'il est également possible d'obtenir une chaîne vide (ou une chaîne de caractères avec espaces), il serait traité comme un argument nul, même avec la "solution rapide" ci-dessus, et échouerait avec la commande [: unary operator expected

C'est le même problème si vous êtes habitué à d'autres langages - vous ne vous attendez pas à ce que le contenu d'une variable soit effectivement imprimé dans le code avant qu'il ne soit évalué.

Voici un exemple qui empêche à la fois le [: too many arguments y el [: unary operator expected erreurs : remplacement de la sortie par une valeur par défaut si elle est vide (dans cet exemple, 0 ), avec des guillemets autour de l'ensemble :

VARIABLE=$(/some/command);
if [ "${VARIABLE:-0}" == 0 ]; then
  # some action
fi 

(ici, l'action se produira si $VARIABLE est 0, ou vide. Naturellement, vous devez changer la valeur 0 (la valeur par défaut) par une autre valeur par défaut si vous souhaitez un comportement différent).


Note finale : Depuis [ est un raccourci pour test tout ce qui précède est également vrai pour l'erreur test: too many arguments (et aussi test: unary operator expected )

0 votes

Un moyen encore meilleur est i=$(some_command); i=$((i)); if [ "$i" == 0 ] ...

1 votes

J'ai rencontré un problème où un Shellscript utilisant BASH comme interpréteur, lorsqu'il était exécuté via le terminal, se passait bien, mais lorsqu'il était exécuté via Crontab, il avait des échecs comme celui-ci et envoyait un email local via Postfix, informant de cette erreur et j'ai découvert qu'il y avait un IF pour une variable qui avait des caractères spéciaux. Les guillemets doubles m'ont sauvé la vie. Merci :) !

0 votes

Master class ! !!

15voto

sdaau Points 6262

Je viens de tomber sur ce post, en obtenant la même erreur, en essayant de tester si deux variables sont les deux vide (ou non vide). Il s'agit en fait d'un comparaison composée - 7.3. Autres opérateurs de comparaison - Guide avancé des scripts Bash et j'ai pensé que je devais noter ce qui suit :

  • J'ai utilisé -e en pensant d'abord que cela signifie "vide" ; mais cela signifie "le fichier existe" - utilisez -z pour les essais à vide variable (chaîne)
  • Les variables de type chaîne doivent être citées
  • Pour la comparaison logique composée ET, soit :
    • utiliser deux test et && les : [ ... ] && [ ... ]
    • ou utiliser le -a dans un seul test : [ ... -a ... ]

Voici une commande de travail (recherche de tous les fichiers txt dans un répertoire, et vidage de ceux qui grep trouve contiennent à la fois deux mots) :

find /usr/share/doc -name '*.txt' | while read file; do \
  a1=$(grep -H "description" $file); \
  a2=$(grep -H "changes" $file); \
  [ ! -z "$a1" -a ! -z "$a2"  ] && echo -e "$a1 \n $a2" ; \
done

Edit 12 Aug 2013 : note de problème connexe :

Notez que lors de la vérification de l'égalité des chaînes de caractères avec la méthode classique test (crochet simple) [ ), vous MUST ont un espace entre l'opérateur "est égal", qui dans ce cas est un simple "est égal". = (bien que deux signes "égal == semble également être accepté comme opérateur d'égalité). Ainsi, cela échoue (silencieusement) :

$ if [ "1"=="" ] ; then echo A; else echo B; fi 
A
$ if [ "1"="" ] ; then echo A; else echo B; fi 
A
$ if [ "1"="" ] && [ "1"="1" ] ; then echo A; else echo B; fi 
A
$ if [ "1"=="" ] && [ "1"=="1" ] ; then echo A; else echo B; fi 
A

... mais ajoutez l'espace - et tout semble parfait :

$ if [ "1" = "" ] ; then echo A; else echo B; fi 
B
$ if [ "1" == "" ] ; then echo A; else echo B; fi 
B
$ if [ "1" = "" -a "1" = "1" ] ; then echo A; else echo B; fi 
B
$ if [ "1" == "" -a "1" == "1" ] ; then echo A; else echo B; fi 
B

0 votes

Pourriez-vous fournir un exemple de shell bash pour ((A || B) && C) ?

0 votes

Voir la question 3826425 y 14964805

0 votes

Cette réponse n'est pas vraiment utile car elle ne vous montre pas comment contenir complètement la commande entre les crochets, ce qui est nécessaire s'il y a une boucle, par exemple.

6voto

wisbucky Points 829

Un autre scénario que vous pouvez obtenir [: too many arguments o [: a: binary operator expected les erreurs sont si vous essayez de tester pour tous les arguments "$@"

if [ -z "$@" ]
then
    echo "Argument required."
fi

Cela fonctionne correctement si vous appelez foo.sh o foo.sh arg1 . Mais si vous passez plusieurs arguments comme foo.sh arg1 arg2 vous obtiendrez des erreurs. C'est parce qu'il est en train d'être étendu à [ -z arg1 arg2 ] ce qui n'est pas une syntaxe valide.

La manière correcte de vérifier l'existence d'arguments est la suivante [ "$#" -eq 0 ] . ( $# est le nombre d'arguments).

5voto

Harsh Gupta Points 31

J'ai également rencontré le même problème. La réponse de @sdaau m'a aidé de manière logique. Voici ce que je faisais, ce qui me semble syntaxiquement correct, mais je reçois l'erreur "too many arguments".

Mauvaise syntaxe :

if [ $Name != '' ] && [ $age != '' ] && [ $sex != '' ] && [ $birthyear != '' ]  && [ $gender != '' ] 
then
    echo "$Name"
    echo "$age"
    echo "$sex"
    echo "$birthyear"
    echo "$gender"
else
    echo "Enter all the values"
fi

dans l'instruction if ci-dessus, si je passe les valeurs des variables comme indiqué ci-dessous, j'obtiens également une erreur de syntaxe.

export "Name"="John"
export "age"="31"
export "birthyear"="1990"
export "gender"="M"

Avec la syntaxe ci-dessous, j'obtiens le résultat attendu. Syntaxe correcte :

if [ "$Name" != ""  -a  "$age" != ""  -a  "$sex" != ""  -a  "$birthyear" != ""   -a  "$gender" != "" ] 
then
    echo "$Name"
    echo "$age"
    echo "$sex"
    echo "$birthyear"
    echo "$gender"
else
    echo "it failed"
fi

Il y a quelques points que nous devons garder à l'esprit

  1. utiliser "" au lieu de "
  2. utiliser -a au lieu de &&
  3. mettez un espace avant et après le signe de l'opérateur comme [ a = b], ne l'utilisez pas comme [ a=b ] dans la condition if.

La solution ci-dessus a donc fonctionné pour moi ! !!

4voto

Kemin Zhou Points 31

Parfois, si vous touchez le clavier par accident et que vous supprimez un espace.

if [ "$myvar" = "something"]; then
    do something
fi

Cela déclenchera ce message d'erreur. Notez que l'espace avant ']' est nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X