tags:

views:

96

answers:

2

Script test.sh:

#!/bin/bash
if [[ $# -eq 0 ]]; then
  echo "no arg"
else
  echo "have arg"
fi

When I ran it as

./test.sh

it said "no arg", which was expected, but if I run it as

sh ./test.sh

it prints "have arg", but it you print $#, it's zero in both cases.

However, the script below

#!/bin/bash
if [ $# -eq 0 ]; then
  echo "no arg"
else
  echo "have arg"
fi

prints "no arg" in both cases.

Could somebody explain this? Why does [[]] interpret $# differently from []. The explanations I've read about "[[]]" weren't clear enough about this...

A: 

In my case (ubuntu 9.04) I also see the following error line ABOVE the "have arg" line:

./test.sh: 6: [[: not found

And indeed that's as it should be; /bin/sh is a symbolic link to 'dash' not 'bash'.

pbr
Yes I guess I overlooked this line in the output and wasn't aware of the fact that sh links to dash instead of bash...Thanks!
dennis2008
+2  A: 

/bin/sh is often a different shell interpreter than bash. On my ubuntu system, it's a symlink to dash. The different shells have different syntax.

[ foo ] and test foo are equivalent in both bash and dash.

[[ foo ]] is a bash expression that is similar to [ ] tests, but with some differences that are noted in man bash.

   [[ expression ]]
          Return a status of 0 or 1 depending on  the  evaluation  of  the
          conditional  expression expression.  Expressions are composed of
          the primaries described  below  under  CONDITIONAL  EXPRESSIONS.
          Word  splitting  and pathname expansion are not performed on the
          words between the [[ and  ]];  tilde  expansion,  parameter  and
          variable  expansion, arithmetic expansion, command substitution,
          process substitution, and quote removal are  performed.   Condi‐
          tional operators such as -f must be unquoted to be recognized as
          primaries.

          When the == and != operators are used, the string to  the  right
          of the operator is considered a pattern and matched according to
          the rules described below under Pattern Matching.  If the  shell
          option  nocasematch  is  enabled, the match is performed without
          regard to the case of alphabetic characters.  The  return  value
          is  0 if the string matches (==) or does not match (!=) the pat‐
          tern, and 1 otherwise.  Any part of the pattern may be quoted to
          force it to be matched as a string.

          An  additional  binary operator, =~, is available, with the same
          precedence as == and !=.  When it is used,  the  string  to  the
          right  of the operator is considered an extended regular expres‐
          sion and matched accordingly (as in regex(3)).  The return value
          is 0 if the string matches the pattern, and 1 otherwise.  If the
          regular expression is syntactically incorrect,  the  conditional
          expression's return value is 2.  If the shell option nocasematch
          is enabled, the match is performed without regard to the case of
          alphabetic characters.  Any part of the pattern may be quoted to
          force it to be matched  as  a  string.   Substrings  matched  by
          parenthesized  subexpressions  within the regular expression are
          saved in  the  array  variable  BASH_REMATCH.   The  element  of
          BASH_REMATCH  with index 0 is the portion of the string matching
          the entire regular expression.  The element of BASH_REMATCH with
          index  n is the portion of the string matching the nth parenthe‐
          sized subexpression.
nilbus
p4bl0's link http://stackoverflow.com/questions/669452/is-preferable-over-in-bash-scripts is very good for explaining what's meant by this man page :)
nilbus