25

I am trying to see if an array is empty in bash

key=[]
key1=["2014"]

I have tried following ways:

[[ -z "$key" ]] && echo "empty" || echo "not Empty" 
[[ -z "$key1" ]] && echo "empty" || echo "not Empty"

Both return 'not Empty'

[[ $key==[] ]] && echo "empty" || echo "not Empty"
[[ $key1==[] ]] && echo "empty" || echo "not Empty"

Both return empty.

4
  • 5
    key=[] isn't an array; it's a regular variable with the value []. Bash doesn't really have empty arrays: it has unset variables (which may or may not have the array attribute set), and it has array variables with one or more values assigned to them. Commented Jan 29, 2021 at 15:58
  • ahhh, i see. Thank you so much for the comment. I guess this is one of the most important things i should know here @chepner Commented Jan 29, 2021 at 18:20
  • Maybe the question could be fixed, in a way to have a useful question about checking array emptyness, and without causing extra troubleshooting in the array definition itself. So, without example code that indeed does not work and can just create problems for newbies landing here. Commented Jan 8, 2024 at 16:21
  • @ValerioBozz Perhaps - but it seems that in its current form many people have found this Q&A useful over the years. I'm assuming many people new to bash makes the same mistake as OP so it would be a shame to make that part of the Q&A go away. Also, taking code directly from questions on SO and expecting that code to work is probably not something many people do, new or not. Commented Jan 8, 2024 at 16:37

2 Answers 2

43

As noted by @cheapner in the comments, you are not defining your arrays correctly.

key=()
key1=("2014" "kdjg")

key is here an empty array and key1 has 2 elements.

This then prints the number of elements in the arrays, which is 0 and 2 respectively:

echo "${#key[@]}"
echo "${#key1[@]}"

And this prints empty and not empty respectively:

if (( ${#key[@]} == 0 )); then
    echo empty
fi

if (( ${#key1[@]} != 0 )); then
    echo not empty
fi
Sign up to request clarification or add additional context in comments.

15 Comments

If you wish for POSIX friendliness, perhaps [ ${#key[@]} -eq 0 ] since many shells do not support (( arithmetic ))
@dawg But, are there bash versions out there that doesn't? I'm assuming a non-historical bash :-)
As stated -- this consideration is for POSIX compliance, not Bash versions. The construct (( C arithmetic )) is a Bash extension and not POSIX compatible. Korn, sh, others, do not have that. ALL have POSIX comparisons however...
@dawg Yes, ok, I tend to use what I find most convenient in the language I'm programming in at the moment and I rarely/never try to find a common denominator for a set of similar languages and only use that subset of functionality. If I'm using bash, arithmetic expansion is surely going to be used.
@ValerioBozz "it probably has to calculate the length of the array just to understand whenever it's empty or not" - It doesn't take longer for it to determine if an empty array is empty then for an array with 1000000 elements. I guess in big O notation that would make it O(1).
|
1

For plain arrays (not associative arrays) empty check, I simply use:

if [[ -z ${array[@]} ]]; then
    # do something
fi

EDIT:

If (and only if) the array certainly will never contain an empty 1st element, testing for only the first element would suffice, which might be faster for large arrays, but would require verification:

[[ -z $array ]] && ...

NOTE: As already stated above, testing the array for size also works - which one's faster, would require verification, too.

BUT this test also works for arrays, which only contain one empty element and appears to be the safest method - for -z the test fails:

array=('')
[[ ${#array[@]} -eq 0 ]] && echo TRUE
[[ ${#array[@]} == 0 ]] && echo TRUE # as string compare
-> no output (OK)

[[ -z ${array[@]} ]] && echo TRUE
-> TRUE (FAIL)

A trick to work around the array single empty element issue with the -z test operator is to use @Q as expansion operator, since it outputs empty quotes - this also works for only checking the 1st array element:

[[ -z ${testA[@]@Q} ]] && echo TRUE
-> no output (OK)

[[ -z ${testA@Q} ]] && echo TRUE
-> no output (OK)

3 Comments

if [ -z "${array[]}" ]; then also works. In this case, must be '' and not '@'. Been bitten by this before.
I suppose you mean ${array[*]}, but this problem would only occur when using single test brackets [ ... ]; AFAIK they're considered deprecated. Personally, I always use double brackets [[ ... ]], which are safer to use and don't require var quoting, unless for some string comparisons.
2: Yes. Some kind of weird character translation happened there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.