Local Variables and Scope
local is what lets a function keep its own working variables private, without accidentally overwriting variables used elsewhere in the script.In this page:
Why local Matters
Without local, any variable assigned inside a function becomes (or overwrites) a global variable, which can silently corrupt state elsewhere in the script that happens to use the same name. local varname=value confines the variable strictly to that function call.
Example: Why local Matters
#!/bin/bash
counter=100
increment() {
local counter=0
counter=$((counter + 1))
echo "Inside function, counter is $counter"
}
increment
echo "Outside function, counter is still $counter"
Login to try C/C++/Java/PHP code in the editor
Global Leakage Without local
If a function assigns to a variable without declaring it local, that assignment affects the global variable of the same name (creating it if it didn't exist), and the change persists after the function returns. This is a common source of hard-to-trace bugs in larger scripts.
Warning: Always use local for a function's own working variables unless you specifically intend to modify a global.
Example: Global Leakage Without local
#!/bin/bash
leaky_function() {
message="set inside function, no local"
}
leaky_function
echo "After call, message is: $message"
Login to try C/C++/Java/PHP code in the editor
Dynamic Scoping: Callees See Caller's Locals
Bash's locals are dynamically scoped, meaning a function called from inside another function can see and use that outer function's local variables, unlike lexically scoped languages where only the enclosing code block matters. This is a distinctive quirk worth knowing even though most scripts don't rely on it directly.
Example: Dynamic Scoping: Callees See Caller's Locals
#!/bin/bash
outer() {
local shared_value="from outer"
inner
}
inner() {
echo "inner sees shared_value as: $shared_value"
}
outer
Login to try C/C++/Java/PHP code in the editor
Separating local Declaration from Command Substitution
Combining local with a command substitution assignment on one line, like local x=$(cmd), can hide cmd's own exit status behind local's exit status. Splitting the declaration and the assignment into two lines preserves the ability to check the substituted command's real exit status.
Example: Separating local Declaration from Command Substitution
#!/bin/bash
check_status() {
local output
output=$(echo "data"; exit 3)
echo "Captured output: $output"
echo "Exit status of the command substitution: $?"
}
check_status
Login to try C/C++/Java/PHP code in the editor
- Forgetting to use
localfor a function's working variables; without it, a variable of the same name used elsewhere in the script (or in another function) gets silently overwritten. - Assuming
localmakes a variable visible to functions called from within the current function; local scope in Bash is only visible in the function it's declared in and functions it calls (dynamic scoping), not hidden from callees, but it is hidden from the caller after the function returns. - Combining
localwith command substitution in a single line, e.g.local x=$(cmd), without realizinglocal's own exit status can maskcmd's exit status -- if you needcmd's status, declare and assign in two separate lines.
local varname=valueinside a function creates a variable that only exists within that function call and disappears when the function returns.- Without
local, a variable assigned inside a function is global by default and persists/overwrites after the function returns. - Bash uses dynamic scoping for locals: a function called from inside another function *can* see the caller's locals, unlike lexical scoping in many other languages.
- Declaring commonly-named loop or temp variables (
i,result,temp) aslocalinside functions avoids subtle bugs from name collisions.
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: