If I have an array with 5 elements, for example:


Using echo ${myarray[4]} I can see what it holds.

But what if I didn't know the number of elements in a given array? Is there a way of reading the last element of an unknown length array? i.e. The first element reading from the right to the left for any array?

I would like to know how to do this in bash.


As of bash 4.2, you can just use a negative index ${myarray[-1]} to get the last element. You can do the same thing for the second-last, and so on; in Bash:

If the subscript used to reference an element of an indexed array evaluates to a number less than zero, it is interpreted as relative to one greater than the maximum index of the array, so negative indices count back from the end of the array, and an index of -1 refers to the last element.

The same also works for assignment. When it says "expression" it really means an expression; you can write in any arithmetic expression there to compute the index, including one that computes using the length of the array ${#myarray[@]} explicitly like ${myarray[${#myarray[@]} - 1]} for earlier versions.

  • 2
    You can do that in ksh and zsh as well.
    – Janis
    Apr 27 '15 at 4:43
  • 5
    With zsh though, by default arrays are 1-indexed, unlike bash and ksh where they are 0-indexed. Apr 27 '15 at 4:49
  • 2
    Yes, of course; the short answer to this question doesn't change, but since the long form was mentioned I thought it necessary to point out the difference in behaviour there. Apr 27 '15 at 5:05
  • 31
    Negative index only work in bash 4.3 and above.
    – cuonglm
    Apr 27 '15 at 15:53
  • 11
    The version of Bash included with Mac OS X as of at least v10.11.5 is only 3.2, so this doesn't work on Macs.
    – Doktor J
    Nov 30 '16 at 23:05

Modern bash (v4.1 or better)

You can read the last element at index -1:

$ a=(a b c d e f)
$ echo ${a[-1]}

Support for accessing numerically-indexed arrays from the end using negative indexes started with bash version 4.1-alpha.

Older bash (v4.0 or earlier)

You must get the array length from ${#a[@]} and then subtract one to get the last element:

$ echo ${a[${#a[@]}-1]}

Since bash treats array subscripts as an arithmetic expression, there is no need for additional notation, such as $((...)), to force arithmetic evaluation.

  • the last one doesn't work for me; I'm using Bash v4.1.2(1): instead of printing the last item, it just prints out the whole array. Oct 4 '16 at 15:34
  • @cuonglm's answer works, however. Oct 4 '16 at 15:53
  • The answer would be even better if you could qualify modern with a version.
    – Samveen
    May 16 '17 at 3:08
  • 1
    Exactly what was needed to make the anwser perfect.
    – Samveen
    May 17 '17 at 9:40
  • 1
    Thank you for this. I was using echo ${a[$((${#a[@]}-1]))} because I didn't know about "bash treats array subscripts as an arithmetic expression". Dec 21 '18 at 6:29

bash array assignment, reference, unsetting with negative index were only added in bash 4.3. With older version of bash, you can use expression in index array[${#array[@]-1}]

Another way, also work with older version of bash (bash 3.0 or better):

$ a=([a] [b] [c] [d] [e])
$ printf %s\\n "${a[@]:(-1)}"


$ printf %s\\n "${a[@]: -1}"

Using negative offset, you need to separate : with - to avoid being confused with the :- expansion.

  • 1
    Make that "${a[@]: -1}" and it will work (besides bash and zsh) also in ksh.
    – Janis
    Apr 27 '15 at 5:09
  • The Kornshell docs (www2.research.att.com/sw/download/man/man1/ksh.html) specify it completely. (Haven't inspected the docs of zsh or bash; but I tested it in all three shells.)
    – Janis
    Apr 27 '15 at 5:20
  • @Janis: re-read bash documentation, it also mentioned about this one, too. Thanks again.
    – cuonglm
    Apr 27 '15 at 5:21


The oldest alternative(s) in bash (Since bash 3.0+) are:

$ a=(aa bb cc dd ee)
$ echo "${a[@]:(-1)}   ${a[@]: -1}   ${a[@]:(~0)}   ${a[@]:~0}"
ee   ee   ee   ee

The space is required to avoid the interpretation of : followed by a minus - as the expansion of "${var:-abc}" (Use Default Values).

The ~ is an arithmetic bitwise negation (equivalent to one's complement or flip all bits). From man bash:


      ! ~         logical and bitwise negation  

Since bash-4.2+ also:

$ echo "${a[-1]}   ${a[(~0)]}"
ee   ee

Since bash 5.0+ also:

$ echo "${a[~0]}"

For all bash versions (older bash):

$ echo "${a[   ${#a[@]}-1   ]}"    # spaces added **only** for readability


For positional arguments (since bash 2.01):

$ set aa bb cc dd ee
$ echo "${@:(-1)} ${@:~0} ${@: -1} ${@:$#}   ${!#}"
ee ee ee   ee

A portable solution for all shells is to use eval:

eval printf '"%s\n"' \"\${$#}\"
  • ...and how do you do it with $@? bash: ${@[@]:(-1)}: bad substitution
    – Tom Hale
    Jun 13 '19 at 12:18
  • 1
    Yes, there is a man bash reference (check the expanded answer at the @ title). @TomHale
    – ImHere
    Jun 13 '19 at 22:28
  • 1
    The @ is not an array (well, not fully an array) in bash and it doesn't accept the index ([]) subscript for individual arguments. You need to use ${@:(-1)} or equivalent. Check expanded entry at the @ title. @TomHale
    – ImHere
    Jun 13 '19 at 22:32
  • @TomHale It looks like the relevant part of the Bash Reference Manual is gnu.org/software/bash/manual/… : "If parameter is ‘@’, the result is length positional parameters beginning at offset. A negative offset is taken relative to one greater than the greatest positional parameter, so an offset of -1 evaluates to the last positional parameter. It is an expansion error if length evaluates to a number less than zero." May 15 at 16:10

Also you can do this:

$ a=(a b c d e f)
$ echo ${a[$(expr ${#a[@]} - 1)]}


$ f

What you're doing is getting all the count of elements in the array and subtract -1 due you're getting all the elements, not starting from the array index that is 0.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.