3

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?

2
  • 2
    shellcheck/SC2155 explains this exact case. A tip: Use shellcheck.net (and better - its editor integrations) 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.) Commented Aug 28, 2019 at 4: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. Commented Aug 28, 2019 at 13:01

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Is there a good reason affectation of the value is done before using declare on that variable? I’d do the declare -i var first, especially with -i, as could change what value is affected in some case, like affecting 4+5, which would be evaluated to 9 in case the variable is declared an integer, but the string 4+5 itself if a “standard” variable. I noticed the the declare -p (or declare -fp) could effectively gives the affectation first, before the declare key word is used. What the subtle bash-candy 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.