Your three examples are not all exactly alike.
In the last two:
if [ "${a}" == 0 ]; then
ffmpeg -framerate 2 -pattern_type glob -i "*.png" -pix_fmt yuv420p output.mp4
If $a
was not quoted, and its value contained characters of $IFS
(by default space, tab and newline) or wildcard characters, this would
cause [
to receive more than three arguments (beside the [
and ]
ones), resulting in an error;
similarly, if the value of $a
was the empty string, this would cause
[
to receive too few arguments:
$ (a=0; [ $a == 0 ] && echo OK)
OK
(but only if $IFS
currently happens not to contain 0
)
$ (a='foo bar'; [ $a == 0 ] && echo OK)
bash: [: too many arguments
(with the default value of $IFS
)
$ (a=; [ $a == 0 ] && echo OK)
bash: [: ==: unary operator expected
(even with an empty $IFS
or with zsh
(that otherwise doesn't implement that implicit split+glob operator upon unquoted expansions))
$ (a='*'; [ $a == 0 ] && echo OK)
bash: [: too many arguments
(when run in a directory that contain at least 2 non-hidden files).
With quoting, no error:
$ (a='foo bar'; [ "$a" == 0 ] && echo OK)
$ (a=; [ "$a" == 0 ] && echo OK)
Your first example is different. The rules about expansion within
double quotes are special when arrays are involved; if a
denotes an
array, then:
$a
is the first element of the array (sticktly speaking it's ${a[0]}
even if the element at indice 0 is not defined);
${a[*]}
or ${a[@]}
are the elements of the array, additionally split at $IFS
(space, tab, newline by default);
"${a[@]}"
is the elements of the array, not split at $IFS
.
So your loop for i in "${indices[@]}"; do ...
does not actually work
the same, depending on the contents of the array. For example:
$ (declare -a a=(a b c); printf '%s\n' $a)
a
$ (declare -a a=(a b c); printf '%s\n' ${a[*]})
a
b
c
$ (declare -a a=(a 'b c'); printf '%s\n' ${a[*]})
a
b
c
$ (declare -a a=(a 'b c'); printf '%s\n' ${a[@]})
a
b
c
$ (declare -a a=(a 'b c'); printf '%s\n' "${a[*]}")
a b c
$ (declare -a a=(a 'b c'); printf '%s\n' "${a[@]}")
a
b c