6

What's the difference between declare foo and foo= in Bash?

If I print out the value of foo, then it's foo and foo="" for declare foo and foo=, respectively.

Are the values of foo and foo="" equivalent? If not, how is it possible to differ between these values (both -n and -z for [[ ... ]] behaves identically)?

$ foo=
$ declare -p foo
declare -- foo=""
$ declare -p bar
bash: declare: bar: not found
$ declare bar
$ declare -p bar
declare -- bar
2
  • This is related, but doesn't answer your question. – pLumo Mar 8 at 9:26
  • Good question! Maybe something like declare only "declares" the variable name, while foo= will assign the null string (compare man bash -> If value is not given, the variable is assigned the null string.). But a similar statement is not given for declare and od returns the same output for both assignments ... So, I'm lost here. – pLumo Mar 8 at 9:30
10

Are the values of foo and foo="" equivalent? If not, how is it possible to differ between these values

No, the former is pretty much like an unset variable. You could use something like declare -x foo to set flags to a variable without setting a value, e.g. here, to mark foo as exported in case it ever gets a value. If you can find a use for that. (It won't be actually exported to commands without a value.)

Use [[ -v name ]] (Bash/ksh/etc.) or [ "${var+set}" = set ] (standard) to tell the difference between an unset and a set-but-empty variable:

$ unset foo
$ declare foo
$ declare -p foo
declare -- foo
$ [[ -v foo ]] && echo is set || echo not set
not set
$ echo ${foo+set}

$ unset foo
$ foo=
$ declare -p foo
declare -- foo=""
$ [[ -v foo ]] && echo is set || echo not set
is set
$ echo ${foo+set}
set

Also, using declare var in a function makes the variable local to the function, a straight assignment doesn't, it assigns to the global variable instead:

$ foo=123 
$ f() { declare foo; declare -p foo; }
$ f; declare -p foo
declare -- foo
declare -- foo="123"

$ g() { foo=; declare -p foo; }
$ g; declare -p foo
declare -- foo=""
declare -- foo=""

Going outside Bash, it seems that Ksh is similar to Bash here, and that in Zsh, there's no difference between foo= and typeset foo, the latter also sets the variable to the empty string:

% unset foo; typeset foo; typeset -p foo; [[ -v foo ]] && echo is set || echo not set
typeset foo=''
is set

% unset foo; foo=; typeset -p foo; [[ -v foo ]] && echo is set || echo not set
typeset foo=''
is set

See also:

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.