1

The declare keyword is optional in bash, so my_var="foobar" is the same as declare my_var="foobar". Does bash/dash actually assign new value to variable or it just declares new variable and hides existing variable with the same name?

#!/bin/sh

GetValue ()
{
    echo "foobar";
    return 1;
}

var1="$(GetValue)" && echo "Successed!" || echo "Failed!";  # Failed!
declare var2="$(GetValue)" && echo "Successed!" || echo "Failed!";  # Successed!

In the snippet above, although both variables were successfully declared and assigned, the use of declare makes a difference between the status code. Why?

oguz ismail
  • 1
  • 16
  • 47
  • 69
Livy
  • 631
  • 4
  • 15
  • 2
    [shellcheck/SC2155](https://github.com/koalaman/shellcheck/wiki/SC2155) explains this exact case. A tip: Use https://www.shellcheck.net/ (and better - its [editor integrations](https://github.com/koalaman/shellcheck#user-content-in-your-editor)) to check script sanity, which is usually faster than typing a question here. (Note: I am not dissuading you from asking questions. Just introducing to a tool that I find quite useful.) – anishsane Aug 28 '19 at 04:33
  • 1
    Despite its name, `declare` really is just used to set attributes on names or (with `-p`) display the value assigned to a name. If `var2` is undefined, it remains undefined after `declare var2`. – chepner Aug 28 '19 at 13:01

1 Answers1

2

The function GetValue along with printing a string to stdout also returns a code 1. So assignment to the variable var1 from the function, though sets the value to foobar, sets an exit code 1 which is a non-zero code causing the part after the || to be invoked.

But remember the same happens in the case with the declare, but the reason you see Successed is because the exit code 1 from the function is suppressed when the declare built-in acts on the variable. So

var2="$(GetValue)"  # sets a non-zero exit code 1
declare var2        # sets a success exit code 0

Since the last foreground command's exit code is the one used in the evaluation of success/failure, the part after &&, which is echo "Successed!" gets invoked.

So, your claim of using declare in the variable assignment makes a difference in the exit code is incorrect, because these two still remain the same as they both set the exit code 1 which triggers the false case.

var1="$(GetValue)" && echo "Successed!" || echo "Failed!";
var2="$(GetValue)" && echo "Successed!" || echo "Failed!"; 

Suggest to always separate the initialization/declaration when using the built-ins local, declare and export

var=5
declare -i var 

is preferred over declare -i var=5.

See Why does local/declare sweep the return code of a command? for more reference on the subject.

Inian
  • 80,270
  • 14
  • 142
  • 161