You are not logged in.
script #1
#!/usr/bin/env bash
f() {
trap 'declare -p HOME' DEBUG # runs the declare command after every 'simple command'
printf '%s\n' 'in function f'
local HOME
HOME=
HOME=egrzfri
unset -v HOME
printf '%s\n' 'return from f'
}
trap 'declare -p HOME' DEBUG # runs the declare command after every 'simple command'
printf '%s\n' 'start script'
printf '%s\n' 'call function f'
f
printf '%s\n' 'back in main script'
Save the script somewhere in your PATH, name it as you wish and run the script with:
script-name='your-chosen-script-name'
bash -x ./${script-name} |& tee ./${script-name}.log
Check the log file for the value of HOME. Note that
- At script level HOME is inherited from environment
- Inside a function:
. as long as HOME has not been declared local, it keeps its global value
. setting the variable local in the function does not initialize it.
Bash just marks the name as belonging to the local scope, no value
is associated with it yet.
It is considered good practice to initialize the variable explicitly
though that is not a requirement.
. assigning HOME a value, it keeps that local value until either it is
assigned a new value or control leaves the function scope
. unset the variable within the function scope does not affect the
global value
. leaving the function scope restores the global variable
These observations hold for bash variables (parameters) as well.
Q&A
Q. Upon entering the function f, HOME has the global value inherited from the
environment. After specifying HOME as a local variable, is it possible for HOME
to regain its inherited global value within function f?
A. Yes, but it is not obvious:
Unsetting HOME within f sets the value of HOME to the empty string.
However, it is possible to restore the global value by creating a new function
on the function stack from within f: function g.
script #2
#!/usr/bin/env bash
f() {
trap 'declare -p HOME' DEBUG
printf '%s\n' 'in function f'
local HOME
HOME=
HOME=egrzfri
unset -v HOME
g(){
trap 'declare -p HOME' DEBUG
unset -v HOME
printf '%s\n' 'in function g'
}
printf '%s\n' 'call function g'
g
printf '%s\n' 'back in function f'
printf '%s\n' 'return from f'
}
trap 'declare -p HOME' DEBUG
printf '%s\n' 'start script'
printf '%s\n' 'call function f'
f
printf '%s\n' 'back in main script'
After 'unset -v HOME' in function g, HOME regains the value inherited
from the environment, just as it had never been changed in function f.
Upon returning from g, HOME has again the value inherited from the environment.
Executive Summary
Unset a variable in an inner function and it loses it's local nature in the wrapping function!
Q. So, if you are writing a new script, should you unset your variables
before using them?
A. In general, no.
You can use environment variables as they are, unless you want to override them
explicitly. Just assigning a new value is sufficient, no need to unset it first.
If your variables are bash parameters, just assign values. no need for unset.
Do take care *not* to inadvertently override environment variables.
That is why it is best to use all capitals for environment variables
another schema for bash parameters (all lowercase or camelcase, as you prefer)
The case where you source another script into your script needs special attention.
You may be importing global parameters and functions.
When you are importing global variables, but you don't use those variables in you script,
and you don't use functions that use those variables, then you can clean up the variables
namespace by unsetting those variables explicitly.
When the imported functions use variables that are *not* declared local, then you will
import such variables when you call such functions from your script, thus polluting
your variable namespace: variables take up entries in the namespace and their values
take up memory space.
If you have access to the sourced script, change it to make the variables local.
If you don't have acces to the sourced script, inform the author of the script and
unset those variables in your own script until the sourced script has been changed.
Want to know more about local variables head over to bash-hackers
There is a script in there that may rack your brains, but also shows how you can
explore the function stack of a bash script, and do some specific debugging in bash.
Q. So, if you are writing a new script, should you initialize your variables
before using them?
A. Yes.
Initialize them to the type they will hold. This is extra information for someone else reading
the script and trying to figure out what it does.
Recommendation
When you use unset, use the option -v for variable or -f for function.
Without option bash will first search for a variable with the specified name and if it does not
find any it will go searching for a function of that name.
Thats all for now, folks
Have fun!
Offline