title: Bash empty array expansion with `set -u`
body: <p>I'm writing a bash script which has <code>set -u</code>, and I have a problem with empty array expansion: bash appears to treat an empty array as an unset variable during expansion:</p>
  
  <pre><code>$ set -u
  $ arr=()
  $ echo "foo: '${arr[@]}'"
  bash: arr[@]: unbound variable
  </code></pre>
  
  <p>(<code>declare -a arr</code> doesn't help either.)</p>
  
  <p>A common solution to this is to use <code>${arr[@]-}</code> instead, thus substituting an empty string instead of the ("undefined") empty array. However this is not a good solution, since now you can't discern between an array with a single empty string in it and an empty array. (@-expansion is special in bash, it expands <code>"${arr[@]}"</code> into <code>"${arr[0]}" "${arr[1]}" …</code>, which makes it a perfect tool for building command lines.)</p>
  
  <pre><code>$ countArgs() { echo $#; }
  $ countArgs a b c
  3
  $ countArgs
  0
  $ countArgs ""
  1
  $ brr=("")
  $ countArgs "${brr[@]}"
  1
  $ countArgs "${arr[@]-}"
  1
  $ countArgs "${arr[@]}"
  bash: arr[@]: unbound variable
  $ set +u
  $ countArgs "${arr[@]}"
  0
  </code></pre>
  
  <p>So is there a way around that problem, other than checking the length of an array in an <code>if</code> (see code sample below), or turning off <code>-u</code> setting for that short piece?</p>
  
  <pre><code>if [ "${#arr[@]}" = 0 ]; then
     veryLongCommandLine
  else
     veryLongCommandLine "${arr[@]}"
  fi
  </code></pre>
  
  <p><strong>Update:</strong> Removed <code>bugs</code> tag due to explanation by ikegami.</p>