• BASH > if, les conditions et les tests

      IF …

      renvoie 0 si l’expression est vraie, 1 si elle est fausse.

       

      if test1 ; then
         ...
      elif test2 ; then 
         ...
      else 
         ...
      fi 

      [ ou [[

      [ est la forme raccourci de TEST
      [[ est la forme raccourci de BASH et permet de faire des tests sur des RegEx :[[ $VAR =~ f{oo,ee,a}d ]] food feed fad

      =~ signale une RegEx

      Avec [[, les variables n'ont pas besoin d'être quottées:

      file="file name"
      [[ -f $file ]] && echo "$file is a file"

      Les parentheses n'ont pas besoin d'être échappées:

      [[ -f $file1 && ( -d $dir1 || -d $dir2) ]]

      string comparisons using < or > respect the current locale when done in [[, but not in [ or test.

      As a rule of thumb, [[ is used for strings and files. If you want to compare numbers, use an ArithmeticExpression, e.g.

      i=0
      while (( i < 10 )); do ...

      Quand utiliser [[ et [

      [ pour une portabilité avec POSIX ou BourneShell.

      [[ pour BASH, Zsh or KornShell.

       

      (( 1 + 1 == 2 ? 1 : $(echo "This doesn't do what you think..." >&2; echo 1) ))
      [[ '1 + 1' -eq 2 && $(echo "...but this probably does what you expect." >&2) ]]
      [ $((1 + 1)) -eq 2 -o $(echo 'No short-circuit' >&2) ]

      [[ can detect the presence of expansions that don't result in a word yet still throw an error if none are specified. Ordinary commands can't.

      ( set -- $(echo 'Unquoted null expansions do not result in "null" parameters.' >&2); echo $# )
      [[ -z $(:) ]] && echo '-z was supplied an arg and evaluated empty.'
      [ -z ] && echo '-z wasn't supplied an arg, and no errors are reported. There's no possible way Bash could enforce specifying an argument here.'
      [[ -z ]] # This will cause an error that ordinary commands can't detect.

      For the very same reason, because ['s operators are just "arguments", unlike [[, you can specify operators as parameters to an ordinary test command. This might be seen as a limitation of [[, but the downsides outweigh the good almost always.

       

      >(COMMAND) Process substitution

      <(COMMAND) Process substitution

       

      [ "$variable" ] || echo 'variable inon déclarée ou vide!' >&2

       

      if [[ $file -nt ${file[1]} ]]; then
          printf 'file %s is newer than %s\n' "${file[@]}"
      fi

       

      expression grouping
      (...)
      [[ $var = img* && ($var = *.png || $var = *.jpg) ]] && echo "$var starts with img and ends with .jpg or .png"
      Pattern matching
      [[ $name = a* ]] || echo "name does not start with an 'a': $name"
      RegularExpression matching
      =~
      [[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "It's Friday the 13th!"
      The -a and -o operators, and ( ... ) grouping, are deprecated.
      if [ "$a" = a ] && [ "$b" = b ]; then ...
      if [ "$a" = a ] || { [ "$b" = b ] && [ "$c" = c ];}; then ...
      Special primitives that [[ is defined to have, but [ may be lacking (depending on the implementation):
      file is newer/older than other file
      -nt / -ot
      [[ $file0 -nt $file1 ]] && echo "$file0 is newer than $file1"
      two files are the same
      -ef
      [[ $input -ef $output ]] && { echo "will not overwrite input file: $input"; exit 1; }
      negation
      !
      [[ ! -u $file ]] && echo "$file is not a setuid file"
      But there are more subtle differences.

       

       

      SI PAS : -z étant l'opposé de -n, on peut écrire : if [ ! -n $VAR ]

      FORME CONDENSÉE

      [ test ] && ... → exécute ... si test est VRAI

      [ test ] || ... → exécute ... si test est FAUX

      [ test ] && ... || --- → exécute ... si test est VRAI, --- si test est FAUX

      ET et OU

      Les opérateurs && et || trouvent aussi leur utilité dans un contexte arithmétique:

      $(( 1 && 2 )) →  1

      $(( 3 && 0 )) →  0

      $(( 4 || 0 )) →  1

      $(( 0 || 0 )) →  0

      ET

      if [ $condition1 ] && [ $condition2 ]
      if [ $condition1 -a $condition2 ]
      if [[ $condition1 && $condition2 ]]
      if [[ $condition1 ]] && [[ $condition2 ]]

       

      if [[ -n $1 ]] && [[ -r $1 ]] ; then
        echo "Le fichier existe et est lisible"
      fi

       

      if [ "$A" -eq 9 ] && [ "$B" -eq 4 ] ; then
         echo "$A est égal à 9 et $B est égal à 4"
      fi

       

      a=toto ; b=gaga
      if [ "$a" = toto ] && [ "$b" = gaga ] ; then
         echo "$a est égal à toto et $b est égal à gaga"
      fi

      OU

      if [ $condition1 ] || [ $condition2 ]
      if [ $condition1 -o $condition2 ]
      if [[ $condition1 || $condition2 ]]

       

      if [[ -z $1 ]] || [[ ! -r $1 ]] ; then
        echo "Soit $1 est vide, soit le fichier est illisible"
        exit 2
      fi

      PLUSIEURS CONDITIONS

      if [ -f $VAR1 ] && [ -f $VAR2 ] && [ -f $VAR3 ] ; then ...

       

      if [[ -f $VAR1 && -f $VAR2 && -f $VAR3 ]] ;then ...

       

      if [ -f $VAR1 -a -f $VAR2 -a -f $VAR3 ]; then ...

      CASE

      case $var in
         "1")
            // si $var vaut un
         ;;
         "2|3")
            // si $var vaut deux ou trois
         ;;
         *)
            // au sinon
         ;;
      esac

      TESTER DES NOMBRES

      [ A -eq B ] vrai si A et B sont égaux (equal)

      [ A -ne B ] vrai si A et B sont différents (not equal)

      [ A -lt B ] vrai si A est strictement inférieur à B (less than)

      [ A -le B ] vrai si A est inférieur ou égal à B (less or equal)

      [ A -gt B ] vrai si A est strictement supérieur à B (greater than)

      [ A -ge B ] vrai si A est supérieur ou égal à B (greater or equal)

      tester si la variable est de type numérique

      VAR=$1
      if [ "$(echo $VAR | grep "^[[:digit:]]*$")" ] ; then
          // VAR est numérique
      fi

       

      [[ $VAR != +([0-9]) ]]

      tester si la variable numérique est de type entier

      if ((var)) 2>/dev/null ; then
          // VAR est un entier
      fi

      TESTER DES CHAINES

      NOTE : les chaines doivent être entourées par des guillemets.

       

      if [ -n "$VAR" ] ; then → $VAR pas vide

      if [ -z "$VAR" ] ; then → $VAR vide

      [ "$a" = "toto" ] →  si $a est égal à "toto"

      [[ "$a" == *"toto"* ]] →  si $a contient "toto"

       

      if grep -q "$substr" <<< "$fullstring"; then echo "Found"; fi

      -q quiet mode

      Les RegEx sont annoncées avec la tilde ~

       

      [[ $VAR =~ ^[0-9] ]] → Si $VAR commence par un chiffre

      Casse insensible

      [ "${VAR,,}" == "toto" ],, met $VAR en minuscule. Donc prendra en compte Toto, TOTO, tOtO, etc.

       

      VAR='Une chaine quelconque';
      [[ ${VAR,,} == *"une"* ]] && echo "Trouvé"  # * pour dire 0 ou plusieurs caractères

       

      [ "chaine1" != "chaine2" ] : vrai si les deux chaînes sont différentes.

      TESTER DES FICHIERS / DOSSIERS

      TESTER SI UN FICHIER EXISTE ET N'EST PAS VIDE :


      [[ -s FICHIER ]] && echo "fichier existe et n'est pas vide"
      [[ -s FICHIER ]] || echo "fichier n'existe pas ou vide"

       

      [ -e $F ] vrai si $F existe (fichier ou répertoire)

      [ -s $F ] vrai si $F existe et si sa taille est supérieure à zéro (non vide)

      [ -f $F ] vrai si $F existe et est un fichier

      [ -d $F ] vrai si $F existe et est un répertoire

      [ -r $F ] vrai si $F existe et est accessible en lecture

      [ -w $F ] vrai si $F existe et est accessible en écriture

      [ -x $F ] vrai si $F existe et est un fichier exécutable ou un répertoire accessible

      [ -d $F ] vrai si $F est un répertoire dans le répertoire courant

      [ -O $F ] vrai si $F appartient à l'utilisateur

      [ -G $F ] vrai si $F appartient au groupe de l'utilisateur

      [ -b $F ] vrai si $F est un périphérique de type bloc (disque, partition)

      [ -c $F ] vrai si $F est un périphérique de type caractère (terminal, modem, port parallèle)

      [ -L $F ] vrai si $F est un lien symbolique

      [ -p $F ] vrai si $F est un tube nommé

      [ A -nt B ] vrai si A et B existent et si A est plus récent que B

      [ A -ot B ] vrai si A et B existent et si A est plus ancien que B

      [ A -ef B ] vrai si A et B représentent un seul et même fichier

      extension de fichier

      if [ ${FICH: -4} == ".txt" ]

       

      ATTENTION, l'espace entre FICH: et -4 est obligatoire.

      ftester si ichiers .bak existent

      FILES="$@"
      for f in $FILES ; do
         if [ -f ${f}.bak ] ; then //si un fichier .bak existe
            continue  //on passe au fichier suivant
         fi
            cp $f $f.bak //exécuté seulement si .bak n'existe pas
      done

      TESTER UNE LIGNE LUE OU UNE COMMANDE

      Ligne lue

      Si on lit un fichier ligne par ligne, et que l'on veut faire un grep dessus :

       

      while read LIGNE ; do
         if echo $LIGNE | grep -q "foo" ; then
            echo "Trouvé"
         fi
      done < fichier

       

      -q pour un mode silencieux (quiet)

      Commande

      value=$( grep -ic "toto" /mon/fichier )
      if [ $value -eq 1 ] ; then
        // trouvé
      fi

       

      -i pour insensible à la casse

      -c pour compter les résultats

      tester un GREP

      if grep -q "bla" fichier && ! grep -q "toto" fichier ; then
        #OK
      fi

       

      -q muet

      ! pour inverser

       

      if grep -Fxq "$VAR" fichier ; then
         # OK
      fi

       

      -F, --fixed-strings Interpret PATTERN as a list of fixed strings, separated by new-lines, any of which is to be matched.

      -x, --line-regexp Select only those matches that exactly match the whole line.

      -q muet

      ASTUCES

      if [ "X$chaine1" = "X$chaine2" ] empêche un message d'erreur si une des variables devait être vide (les caractères "X" postfixés se neutralisent).

       

      Les combinaisons de tests

      SI ! { test1 || test2 } ALORS commandes FIN : exécute les commandes si NI test1 NI test2 sont VRAIS

       

      structure TANT QUE ... FAIRE

      While va répéter la boucle tant que le test est vrai : while test; do action1 action2; done

      Until va répéter la boucle jusqu'à ce que le test soit vrai : until test; do action1 action2; done

       

      Pour incrémenter : let $[ i+=1 ]

       

      ---

       

      Tests [ ]

      Les tests sont réalisés avec la commande interne [ ].
      Il doit toujours y avoir des espaces à l'intérieur de [ ] :

      [ $i -lt 10 ]

      A l'aide des opérateurs && (ET) et || (OU) il est possible d'utiliser les tests pour exécuter des commandes selon des conditions :

      [ $i -lt 10 ]&& echo $i

      [ -f $fichier ] || echo $fichier n'est pas un fichier

      Paramètres pour les tests [ ]

      Chaînes :

      s1 # Vrai si la chaîne n'est pas vide
      s1 = s2 # Vrai si les chaînes sont identiques

      ! condition # Retour l'opposé de la condition

      Opérateurs dans les tests :

      -a # AND ou ET
      -o # OR ou OU

       

      CASE

      case $variable in
      1) echo "toto"
      ;;
      2) echo "titi"
      ;;
      *) echo "defaut"
      esac

       

      FOR

      for i in $* ; do
      echo $i
      done
      for i in `ls` ; do
      echo $i
      done

      Attention si vous avez des espaces dans des fichiers que vous souhaitez garder, il faut changer la variable IFS :

      OLDIFS=${IFS}
      IFS=$(echo -en "\n\b")
      for i in $(grep chaine *) ; do
         vos_commandes $i
      done
      IFS=${OLDIFS}
      i=1
      while [ $i -le 3 ] ; do
         echo $i
         i=`expr $i + 1`
      done
      In Bash, test and [ are builtins.

      TESTER UN GREP

      grep -q renvoie 0 si OK.

       

      if grep -q PATTERN file.txt; then

          echo found
      else
          echo not found
      fi

       

      As a quick note, when you do something like if [ -z "$var" ]…, it turns out that [ is actually a command you're running, just like grep. On my system, it's /usr/bin/[. (Well, technically, your shell probably has it built-in, but that's an optimization. It behaves as if it were a command). It works the same way, [ returns a zero exit code for true, a non-zero exit code for false. (test is the same thing as [, except for the closing ])

      The double bracket enables additional functionality.
      For example, you can use && and || instead of -a and -o and there's a regular expression matching operator =~.

      echo f{oo,ee,a}d
      food feed fad
      for num in {000..2}; do echo "$num"; done
      000
      001
      002
      echo {00..8..2}
      00 02 04 06 08
      echo {D..T..4}
      D H L P T

      Double parentheses are used for arithmetic operations:
      ((a++))
      ((meaning = 42))
      for ((i=0; i<10; i++))
      echo $((a + b + (14 * c)))

      and they enable you to omit the dollar signs on integer and array variables and include spaces around operators for readability.

      Single brackets are also used for array indices:

      Curly brace are required for (most/all?) array references on the right hand side.

      ephemient's comment reminded me that parentheses are also used for subshells. And that they are used to create arrays.

      array=(1 2 3)
      echo ${array[1]}
      2

      Excellent! Since this tripped me up a little, I should point out that ${var/foo/bar} will only replace the first occurrence of 'foo' with 'bar' in the string represented by 'var'.
      To replace all occurrences, just double the first forward slash. E.g.$var="foo_foo_baz"; echo ${var//foo/bar}; will print: bar_bar_baz. – JJC May 23 '12 at 14:34
      4

      Also for completeness, I just came across this in an old script: $[expression] ; this is the old, deprecated arithmetic expression syntax for the newer, preferred syntax: $((expression)) – michael_n Oct 6 '12 at 7:53
      1

      @DennisWilliamson Another use of curly braces in bash is creating sequences, as peripherally mentioned below (stackoverflow.com/a/8552128/2749397) As I would like to comment a bit this feature (as you didn't mention it ;-) I'm taking the liberty of using the most voted answer as a vehicle... Two examples of sequence literals: echo {01..12} -> 01 02 03 04 05 06 07 08 09 10 11 12 (note the initial zero); echo {C..Q} -> C D E F G H I J K L M N O P Q. Its main use is in loops, e.g., for cnt in {01..12} ; do ... ${cnt} ... ; done – gboffi Oct 24 '14 at 14:41

      A single bracket ([) usually actually calls a program named [; man test or man [ for more info. Example:

      $ VARIABLE=abcdef
      $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
      yes

      The double bracket ([[) does the same thing (basically) as a single bracket, but is a bash builtin.

      $ VARIABLE=abcdef
      $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
      no

      Parentheses (()) are used to create a subshell. For example:

      $ pwd
      /home/user
      $ (cd /tmp; pwd)
      /tmp
      $ pwd
      /home/user

      As you can see, the subshell allowed you to perform operations without affecting the environment of the current shell.

      4a. Braces ({}) are used to unambiguously identify variables. Example:

      $ VARIABLE=abcdef
      $ echo Variable: $VARIABLE
      Variable: abcdef
      $ echo Variable: $VARIABLE123456
      Variable:
      $ echo Variable: ${VARIABLE}123456
      Variable: abcdef123456

      4b. Braces are also used to execute a sequence of commands in the current shell context, e.g.

      $ { date; top -b -n1 | head ; } >logfile
      # 'date' and 'top' output are concatenated,
      # could be useful sometimes to hunt for a top loader )

      $ { date; make 2>&1; date; } | tee logfile
      # now we can calculate the duration of a build from the logfile

      There is a subtle syntactic difference with ( ), though (see bash reference) ; essentially, a semicolon ; after the last command within braces is a must, and the braces {, } must be surrounded by spaces.

       

      Well, [ is actually a builtin in Bash, but it is supposed to act like /bin/[ as opposed to the [[ builtin. [[ has different features, like more logical operations and different quoting roles. Additionally: single parentheses are also used for arrays, process substitution, and extended globs; double parentheses are used for arithmetic; curly braces {} are used for command grouping or multitudes of types of parameter expansion or brace expansion or sequence expansion. I'm sure I've missed some other uses too... – ephemient Feb 2 '10 at 22:46

      Good catch. There are a million of 'em.

      The double-equals in the expression if [ $VARIABLE == abcdef ] is a bashism that -- although it works -- should probably be avoided; either explicitly use bash (if [[ ...==...]]) or make it clear that you're using the more traditional conditional ( if [ "$VARIABLE" = "abcdef" ] ). Arguably, scripts should start out as simple and portable as possible, up until they really do need features specific to bash (for one reason or another). But in any case, the intent should be clear; "=" and "==" and "[[" and "[" do work differently and their usage should be consistent.

       

      Curly Brackets

      ${variable}                             Parameter substitution
      ${!variable}                            Indirect variable reference
      { command1; command2; . . . commandN; } Block of code
      {string1,string2,string3,...}           Brace expansion
      {a..z}                                  Extended brace expansion
      {}                                      Text replacement, after find and xargs

      Parentheses

      ( command1; command2 )             Command group executed within a subshell
      Array=(element1 element2 element3) Array initialization
      result=$(COMMAND)                  Command substitution, new style
      >(COMMAND)                         Process substitution
      <(COMMAND)                         Process substitution

      Double Parentheses

      (( var = 78 ))            Integer arithmetic
      var=$(( 20 + 5 ))         Integer arithmetic, with variable assignment
      (( var++ ))               C-style variable increment
      (( var-- ))               C-style variable decrement
      (( var0 = var1<98?9:21 )) C-style ternary operation

       

      echo $SHELL
      /bin/bash
      ~:$ echo ${#SHELL}
      9
      ARRAY=(one two three)
      echo ${#ARRAY}
      3
      echo ${TEST:-test}
      test
      echo $TEST
      export TEST=a_string
      echo ${TEST:-test}
      a_string
      echo ${TEST2:-$TEST}
      a_string
      echo $TEST2
      echo ${TEST2:=$TEST}
      a_string
      ~:$ echo $TEST2
      a_string
      ~:$ export STRING="thisisaverylongname"
      ~:$ echo ${STRING:4}
      isaverylongname
      ~:$ echo ${STRING:6:5}
      avery
      ~:$ echo ${ARRAY[*]}
      one two one three one four
      ~:$ echo ${ARRAY[*]#one}
      two three four
      ~:$ echo ${ARRAY[*]#t}
      one wo one hree one four
      ~:$ echo ${ARRAY[*]#t*}
      one wo one hree one four
      ~:$ echo ${ARRAY[*]##t*}
      one one one four
      ~:$ echo $STRING
      thisisaverylongname
      ~:$ echo ${STRING%name}
      thisisaverylong
      ~:$ echo ${STRING/name/string}
      thisisaverylongstring

       

      echo ${#ARRAY} displays three, because of the first element of the ARRAY contains three characters, not because it contains three elements! To print the number of elements use echo ${#ARRAY[@]}.

      echo ${TEST:-test} I did not get it. Thanks

       

       

      When should the new test command [[ be used, and when the old one [? If portability to the BourneShell is a concern, the old syntax should be used. If on the other hand the script requires BASH or KornShell, the new syntax is much more flexible.

      shareimprove this answer

      What is the difference between test, [ and [[ ?

      [ ("test" command) and [[ ("new test" command) are used to evaluate expressions. [[ works only in Bash, Zsh and the Korn shell, and is more powerful; [ and test are available in POSIX shells. Here are some examples:

      #POSIX
      [ "$variable" ] || echo 'variable is unset or empty!' >&2
      [ -f "$filename" ] || printf 'File does not exist or is not a regular file: %s\n' "$filename" >&2

      if [[ ! -e $file ]]; then
      echo "File doesn't exist or is in an inaccessible directory or is a symlink to a file that doesn't exist: $file" >&2
      fi

      if [[ $file -nt ${file[1]} ]]; then
      printf 'file %s is newer than %s\n' "${file[@]}"
      fi

      To cut a long story short: test implements the old, portable syntax of the command. In almost all shells (the oldest Bourne shells are the exception), [ is a synonym for test (but requires a final argument of ]). Although all modern shells have built-in implementations of [, there usually still is an external executable of that name, e.g. /bin/[. POSIX defines a mandatory feature set for [, but almost every shell offers extensions to it. So, if you want portable code, you should be careful not to use any of those extensions.

      [[ is a new improved version of it, and is a keyword, not a program. This makes it easier to use, as shown below. [[ is understood by KornShell, Zsh and BASH (e.g. 2.03), but not by other POSIX shell implementations (like posh, yash or dash) or the BourneShell .

      Although [ and [[ have much in common, and share many expression operators like "-f", "-s", "-n", "-z", there are some notable differences. Here is a comparison list:

      expression grouping
      (...)
      [[ $var = img* && ($var = *.png || $var = *.jpg) ]] && echo "$var starts with img and ends with .jpg or .png"

      Pattern matching
      [[ $name = a* ]] || echo "name does not start with an 'a': $name"

      RegularExpression matching
      =~
      [[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "It's Friday the 13th!"

      The -a and -o operators, and ( ... ) grouping, are deprecated.
      if [ "$a" = a ] && [ "$b" = b ]; then ...
      if [ "$a" = a ] || { [ "$b" = b ] && [ "$c" = c ];}; then ...

      Special primitives that [[ is defined to have, but [ may be lacking (depending on the implementation):
      file is newer/older than other file
      -nt / -ot
      [[ $file0 -nt $file1 ]] && echo "$file0 is newer than $file1"
      two files are the same
      -ef
      [[ $input -ef $output ]] && { echo "will not overwrite input file: $input"; exit 1; }

      negation
      !
      [[ ! -u $file ]] && echo "$file is not a setuid file"

      But there are more subtle differences.

      Avec [[, les variables n'ont pa besoin d'être quottées:
      file="file name"
      [[ -f $file ]] && echo "$file is a file"
      Les parentheses n'ont pas besoin d'être échappées:
      [[ -f $file1 && ( -d $dir1 || -d $dir2) ]]

      string comparisons using < or > respect the current locale when done in [[, but not in [ or test.

      As a rule of thumb, [[ is used for strings and files. If you want to compare numbers, use an ArithmeticExpression, e.g.
      i=0
      while (( i < 10 )); do ...

      When should the new test command [[ be used, and when the old one [? If portability to POSIX or the BourneShell is a concern, the old syntax should be used.
      If on the other hand the script requires BASH, Zsh or KornShell, the new syntax is much more flexible.

      See the Tests and Conditionals chapter in the BashGuide.

      Theory

      The theory behind all of this is that [ is a simple command, whereas [[ is a compound command. [ receives its arguments as any other command would, but most compound commands introduce a special parsing context which is performed before any other processing. Typically this step looks for special reserved words or control operators specific to each compound command which split it into parts or affect control-flow. The Bash test expression's logical and/or operators can short-circuit because they are special in this way (as are e.g. ;;, elif, and else). Contrast with ArithmeticExpression, where all expansions are performed left-to-right in the usual way, with the resulting string being subject to interpretation as arithmetic.

      The arithmetic compound command has no special operators. It has only one evaluation context - a single arithmetic expression. Arithmetic expressions have operators too, some of which affect control flow during the arithmetic evaluation step (which happens last).

      (( 1 + 1 == 2 ? 1 : $(echo "This doesn't do what you think..." >&2; echo 1) ))

      Test expressions on the other hand do have "operators" as part of their syntax, which lie on the other end of the spectrum (evaluated first).

      [[ '1 + 1' -eq 2 && $(echo "...but this probably does what you expect." >&2) ]]

      Old-style tests have no way of controlling evaluation because its arguments aren't special.

      [ $((1 + 1)) -eq 2 -o $(echo 'No short-circuit' >&2) ]

      Different error handling is made possible by searching for special compound command tokens before performing expansions. [[ can detect the presence of expansions that don't result in a word yet still throw an error if none are specified. Ordinary commands can't.

      ( set -- $(echo 'Unquoted null expansions do not result in "null" parameters.' >&2); echo $# )
      [[ -z $(:) ]] && echo '-z was supplied an arg and evaluated empty.'
      [ -z ] && echo '-z wasn't supplied an arg, and no errors are reported. There's no possible way Bash could enforce specifying an argument here.'
      [[ -z ]] # This will cause an error that ordinary commands can't detect.

      For the very same reason, because ['s operators are just "arguments", unlike [[, you can specify operators as parameters to an ordinary test command. This might be seen as a limitation of [[, but the downsides outweigh the good almost always.

 

Aucun commentaire

 

Laissez un commentaire