Behavior of Arrays in bash scripting and zsh shell (Start Index 0 or 1?)
TL;DR:
bash
array indexing starts at0
(always)zsh
array indexing starts at1
(unless optionKSH_ARRAYS
is set)
To always get consistent behaviour, use:
${array[@]:offset:length}
Explanation
For code which works in both bash
and zsh
, you need to use the offset:length
syntax rather than the [subscript]
syntax.
Even for zsh
-only code, you'll still need to do this (or use emulate -LR zsh
) since zsh
's array subscripting basis is determined by the KSH_ARRAYS
option.
Eg, to reference the first element in an array:
${array[@]:0:1}
Here, array[@]
is all the elements, 0
is the offset (which always is 0-based), and 1
is the number of elements desired.
Arrays in Bash are indexed from zero, and in zsh they're indexed from one.
But you don't need the indices for a simple use case such as this. Looping over ${array[@]}
works in both:
files=(file*)
for f in "${files[@]}"; do
echo "$f"
done
In zsh you could also use $files
instead of "${files[@]}"
, but that doesn't work in Bash. (And there's the slight difference that it drops empty array elements, but you won't get any from file names.)
Also, don't use $(ls file*)
, it will break if you have filenames with spaces (see WordSpliting on BashGuide), and is completely useless to begin with.
The shell is perfectly capable of generating filenames by itself. That's actually what will happen there, the shell finds all files with names matching file*
, passes them to ls
, and ls
just prints them out again for the shell to read and process.