47

In bash, what is the difference in declare -r and readonly?

$ declare -r a="a1" $ readonly b="b1" 

I'm not sure which to choose.

1 Answer 1

58

tl;dr readonly uses the default scope of global even inside functions. declare uses scope local when in a function (unless declare -g).

At first glance, no difference.

Examining using declare -p

$ declare -r a=a1 $ readonly b=b1 $ declare -p a b declare -r a="a1" declare -r b="b1" # variable a and variable b are the same 

Now review the difference when defined within a function

# define variables inside function A $ function A() { declare -r x=x1 readonly y=y1 declare -p x y } $ A declare -r x="x1" declare -r y="y1" # ***calling function A again will incur an error because variable y # was defined using readonly so y is in the global scope*** $ A -bash: y: readonly variable declare -r x="x1" declare -r y="y1" # after call of function A, the variable y is still defined $ declare -p x y bash: declare: x: not found declare -r y="y1" 


To add more nuance, readonly may be used to change a locally declared variable property to readonly, not affecting scope.

$ function A() { declare a="a1" declare -p a readonly a declare -p a } $ A declare -- a="a1" declare -r a="a1" $ declare -p a -bash: declare: a: not found 


Note: adding -g flag to the declare statement (e.g. declare -rg a="a1") makes the variable scope global. (thanks @chepner).

Note: readonly is a "Special Builtin". If Bash is in POSIX mode then readonly (and not declare) has the effect "returning an error status will not cause the shell to exit".

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

7 Comments

Note that as of bash 4.2, declare -gr seems to be identical to readonly.
Looks like there is no difference between readonly and declare -r. declare inside a function would always create local variables unless the -g flag is specified.
i like when you answer your self, and answer after 4+ years is still best answer
Re: "readonly will make the variable scope global": That's misleading; if a variable is already local, then readonly won't suddenly make it global. It would be more correct to say that readonly doesn't affect variable scope at all, and global scope is the default scope.
Thanks @ruakh . How embarrassing, that was very poorly worded for a long time. Fixed.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.