Search code examples
bashspecial-characters

Testing the "$@" for being null- strange result


I'm checking the following code:

#!/usr/bin/env bash

set -o errexit
set -o nounset

if [ -n "$@" ]; then
    echo "not null";
else
    echo "null";
fi

This means that if I call my script like so ./my-script.sh parameter it should result with not null and when called like so ./my-script.sh it should say null.

Documentation says that -z means string is null, that is, has zero length and -n means that string is not null.

For some reason my code always claims that $@ is not null.

Why is that?

When I replace -n with -z and swap the content like so:

if [ -z "$@" ]; then
    echo "null";
else
    echo "not null";
fi

then it works correctly.


Solution

  • "$@" isn't a single string: It expands to a variable number of items. If, say, you have ./yourscript one two three, then [ -n "$@" ] becomes [ -n one two three ], which isn't valid syntax. Or if you have zero arguments, it becomes [ -n ], which is true. ([ -z ] is also true, because [ anything ] checks whether anything is an empty string, and "-z" is a non-empty string, just as "-n" is).

    If you want to know if "$@" is empty, check $# instead, which will tell you how many items it contains.

    if [ "$#" -eq 0 ]; then
      echo "null"
    else
      echo "not null"
    fi